Details
-
Improvement
-
Status: Closed
-
Normal
-
Resolution: Fixed
-
None
-
None
-
None
Description
This idea came out of the effort spent working on SERVER-502. In the process of working that ticket, I found myself struggling to thread the java argument vector through the service management framework.
This commentary includes puppetserver to provide a concrete example, but the goal is to make this generic for all ezbake projects.
The idea is to simplify the complexity of starting the puppetserver daemon, specifically foss/ext/debian/ezbake.init.erb.
The final command line argument vector used to spawn the daemon begins life in the init script. The init script sources additional arguments from the defaults file, which is end-user modifiable. The init script then augments the argument vector with additional, vendor-managed, arguments, e.g. -XX:OnOutOfMemoryError and -Djava.security.egd.
This argument vector is stored as a BASH string variable, which is problematic because shell escaping in bash is notoriously difficult, especially when passing the vector through multiple layers.
The init script then passes the arguments to start-stop-daemon, which has it's own set of interesting behaviors targeted at changing the effective user id, checking if the daemon has already been spawned, etc...
start-stop-daemon then passes the arguments to bash and augments the behavior of the command by redirecting STDOUT to a log file.
Finally, bash, spawned by a forked copy of start-stop-daemon, invokes java.
This is complicated and fairly difficult to troubleshoot and reason about.
The proposed solution is to consolidate all of the argument vector processing into a single script. Ruby, or any other language that transparently exposes the exec() system call in combination with support for a proper Array data structure would be much better than SH or BASH for this purpose.
If we consider this script implemented as a puppetserver daemonize subcommand, then the responsibility of this sub-command could be as follows:
1. Handle redirection of output file descriptors.
2. Initialize the argument vector with vendor-supplied mandatory arguments.
3. Augment the argument vector with mandatory, but user-configurable arguments.
4. Augment the argument vector with optional, user-configurable arguments.
5. Expose a simplified interface to the service management framework, e.g. the service framework should not have to concern itself with modifying the argument vectors, it should need only call puppetserver daemonize after switching to the correct effective user ID for the service.
This script would purposefully avoid taking the responsibility of setuid(), leaving that responsibility for the service management framework, e.g. start-stop-daemon or systemd, etc...
Threading the argument vector itself becomes unnecessary. Elimination the threading simplifies the behavior. The script that constructs the argument vector is the same script that executes the daemon process, therefore the argument vector can be passed almost directly and transparently to the exec() system call.
Items 1 and 2 are handled by the init script today, which is awkward because the redirection leads us to thread the argument vector through both start-stop-daemon and through bash. With this proposal threading through bash is unnecessary.
Items 3 and 4 are handled by the defaults file today, which is complicated because the concerns are not well separated. We have both user-modifiable, but optional, and user-modifiable, but mandatory arguments coming from the same place.
Item 5 is not implemented at all today.
Attachments
Issue Links
- relates to
-
SERVER-441 puppetserver foreground can fail if /var/run/... directory missing
-
- Closed
-
-
SERVER-502 Ubuntu 14.04 pre-suite fix
-
- Closed
-
-
SERVER-509 CLI tooling to validate configuration files
-
- Closed
-