When start-stop-daemon is has arguments for the program it is going to execute, and they contain spaces and single or double quotes, they are not evaluated correctly. Reproducible: Always Steps to Reproduce: (sorry about the submission format, my file upload isn't working right) First, our test script (args.pl): --- START CUT --- #!/usr/bin/perl for(my $i=0;$i < @ARGV;$i++) { print STDERR "Arg$i: ".$ARGV[$i]."\n"; } --- END CUT --- Now try this sequence: OPTS="-arg3 'arg4a arg4b'" /sbin/start-stop-daemon --start --exec ./args.pl -- arg1 arg2 "${OPTS}" We get this output: Arg0: arg1 Arg1: arg2 Arg2: -arg3 'arg4a arg4b' This isn't correct... Now try this (removing the " from around ${OPTS}) OPTS="-arg3 'arg4a arg4b'" /sbin/start-stop-daemon --start --exec ./args.pl -- arg1 arg2 ${OPTS} We get this output: Arg0: arg1 Arg1: arg2 Arg2: -arg3 Arg3: 'arg4a Arg4: arg4b' Again, this isn't right! Actual Results: This causes anything that depends on having multiple inputs to throw errors in various ways. For example this error from slapd: slapd[19627]: daemon: listen URL ""ldap://[::]" parse error=3 slapd[19627]: slapd stopped. slapd[19627]: connections_destroy: nothing to destroy. Expected Results: We should get this output: Arg0: arg1 Arg1: arg2 Arg2: -arg3 Arg3: arg4a arg4b As a temporary workaround putting 'eval' in front of every invocation of start- stop-daemon handles this.
Azarah: i'm told you are the person to resolve this.
It is not a problem with start-stop-daemon, its bash due to the args being passed as an env variable: ------------------------------- nosferatu root # (OPTS="-arg3 'arg4a arg4b'"; ./args.pl $OPTS) Arg0: -arg3 Arg1: 'arg4a Arg2: arg4b' nosferatu root # ./args.pl -arg3 'arg4a arg4b' Arg0: -arg3 Arg1: arg4a arg4b nosferatu root # ------------------------------- Aron, know a kludge we can use to 'fix' this ?
Using eval is how I was doing it for now. (OPTS="-arg3 'arg4a arg4b'"; eval ./args.pl ${OPTS})
Using eval is the only sane way to do this, and it makes sense, besides. When the list of arguments contains shell metacharacters (such as quotes), it's only sensible to use the shell (via eval) to interpret the quoting. The only question is where to put the eval. One possibility would be to turn all variables in /etc/conf.d/* into arrays on-the-fly using eval in /sbin/runscript.sh... for example: vars_in_file() { local conf=$1 ( eval "`export | sed 's/-/+/'`" # need double-quotes set -a # export all vars . $confd # load up the config export | sed 's/^declare -x //;s/=.*//' ) # print the varlist } # Find what vars are set in the config file varlist=`vars_in_file /etc/conf.d/gpm` # Now source the config file . $confd # And create variables for the arrays for v in $varlist; do eval "${v}_ARRAY=(\$$v)" done Then you would use them in the initscript like this: start-stop-daemon blah blah "${OPTS_ARRAY[@]}" Now that I've written all that, it seems like heavy overkill to me. The casual reader/writer of /etc/init.d scripts won't have any idea that *_ARRAY variables are being automagically created. Probably the best thing is simply to prefix calls to start-stop-daemon with "eval" as Robin is already doing. I don't recommend hiding the eval (via a function, that is) because it would be completely non-obvious to init-script developers, who should be able to expect bash to act like bash.
I vote for using 'eval' explictly in /etc/init.d/ files.
Same here, as it will also be a more case specific thing - most things do not have issues with this, as they do not need in normal instance quoted arguments like you need with slapd.
Robin, to you, close if you have slapd fixed.
Yes, eval is in the releases of openldap for a while.