views:

1160

answers:

3

Hi, I have been trying to make an init script using start-stop-daemon. I am stuck on the arguments to the daemon. I want to keep these in a variable at the top of the script but I can't get the quotations to filter down correctly.

I'll use ls here so we don't have to look at binaries and arguments that most people wont know or care about.

The end result I am looking for is for start-stop... to run ls -la "/folder with space/"

DAEMON=/usr/bin/ls 
DAEMON_OPTS='-la "/folder with space/"'

start-stop-daemon --start --make-pidfile --pidfile $PID --exec $DAEMON -- $DAEMON_OPTS

Double escaping the options and trying innumerable variations of quotations do not help... Then they end up at the daemon they are always messed up. Enclosing $DAEMON_OPTS in quotes changes things... then they are seen as one since quote... never the right number though :)

Echoing the command-line (start-stop...) prints exactly the right stuff to screen. But the daemon (the real one, not ls) complains about the wrong number of arguments.

How do I specify a variable so that quotes inside it are brought along to the daemon correctly?

Thanks, Martin

+2  A: 

Try

DAEMON_OPTS="-la '/folder with space/'"
start-stop-daemon --start ... -- $DAEMON_OPTS

What happens is that the outer quotes of DAEMON_OPTS are stripped but the inner (single quotes) remain. So the next line will read:

start-stop-daemon --start ... -- -la '/folder with space/'

which is what you want.

It is also possible to achieve the same effect with escaping but you need a lot of escapes for this: First, to protect the quotes during the assignment, then later when the start line is parsed and variables are expanded and maybe even once more or less. :) bash -x is your friend for things like that.

[EDIT] The code above does work with Bourne and Korn shell on anything but Linux. On Linux, with ksh or bash, the shell will add additional quotes which mess up the whole thing:

FOLDER="/folder with space/"
DAEMON_OPTS="-la $FOLDER"
start-stop-daemon --start ... -- $DAEMON_OPTS

If you run it with -x, you'll see:

FOLDER='/folder with space/'
DAEMON_OPTS='-la ~/folder with space/'
ls -la '~/folder' with space/

So only the first word gets protection (probably because it contains a special character). If I add single quotes around $FOLDER, I get:

FOLDER='/folder with space/'
DAEMON_OPTS='-la '\''~/folder with space/'\'''
ls -la ''\''~/folder' with 'space/'\'''

Well done. Workaround: Split the options into two variables: One with the options and the other with the path:

start-stop-daemon --start ... -- $DAEMON_OPTS "$DAEMON_PATH"

[EDIT2] This works, too:

FOLDER="$HOME/folder with space/"
opt[0]=-la
opt[1]=$FOLDER
ls "${opt[@]}"

i.e. put the words into an array.

Aaron Digulla
Maybe I'm doing something wrong, but this solution doesn't work when I try it?
Thomas Padron-McCarthy
Yep, doesn't work with bash :/ I've used this successfully to pass arguments to subscripts by using a loop over the arguments and using `args="$args '$opt'"` and then using `$cmd $args` (no quotes). Works with Bourne and Korn Shell.
Aaron Digulla
Unless you're using ksh on linux (tested with ksh-93s-59.7).
Aaron Digulla
OK så in short the answer is: Ugly workaround?I say ugly since my real list of parameters as a wee bit longer and the end-result of splitting the variables is almost the same as hard-coding them in place. I have more like DAEMON_OPTS="-a -b 'path' -c '/usr/bin/program args' param" and so on. I still thank you for the detailed explanation. I'll leave the question unanswered a while in hope of another answer.
Martin Westin
Then use the array solution.
Aaron Digulla
A: 

Have you tried doing it the other way around with the quotes? Like this:

DAEMON_OPTS='-la "/folder with space/"'

I'm not sure, but that might work?

(I would have posted this as a comment to the previous answer, if only I had had enough reputation to do so).

Enfors
I did try that and any other quote combination I know of... not luck.
Martin Westin
+1  A: 

I thought I'd post the final quotations used in my working init script:

COMMAND="/path/to/script -opt param param2 param3"
DAEMON_OPTS=" 0.0.0.0:$PORT -dest $OUTPUT_DIRECTORY -command"

start-stop-daemon --start --background --make-pidfile --pidfile $PID --exec $DAEMON -- $DAEMON_OPTS "\"$COMMAND\""

Obviously an incomplete and non-functional example but I hope you get the gist of it. The double quotations with the inner pair escaped is what did the trick.

Martin Westin