Bash: executing su -c breaks $@

bashshell-scriptsu

Bash version: GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

This works fine:

#!/bin/bash
exec /usr/local/bin/python2.7 /app/add_container_host.py $@

But I need to run it as a certain user, so I've changed it to:

#!/bin/bash
su -c '/usr/local/bin/python2.7 /app/add_container_host.py $@' $USER

and the Python script is no longer getting the arguments.

I've tried changing the single-quote to double quote and that's supplying the $@ to su -c itself, not to the Python script.

Is there a way to pass $@ to the python script while running it as su -c?

Best Answer

Your issue is the quotes you're using. You need to use double quotes so that the variables within, $@, can be expanded, otherwise they'll remain literals and never get expanded.

Here's an example

$ cat runme.bash
#!/bin/bash

echo "run with double quotes"
su -c "echo $@" user1

echo "run with single quotes"
su -c 'echo $@' user1

$ ./runme.bash "a b c"
run with double quotes
a b c
run with single quotes

$

You also have to pass the list of arguments in as a quoted list, otherwise the su -c ... command gets confused and starts trying to parse the 2nd argument as the user that you want to su as.

Another example

$ ./runme.bash a b c
run with double quotes
su: user b does not exist
run with single quotes

$

Debugging tip

If you want to see what the script is actually doing you can run it with the -x switch to bash.

bare arguments
$ bash -x ./runme.bash a b c
+ echo 'run with double quotes'
run with double quotes
+ su -c 'echo a' b c user1
su: user b does not exist
+ echo 'run with single quotes'
run with single quotes
+ su -c 'echo $@' user1

$
quoted arguments
$ bash -x ./runme.bash "a b c"
+ echo 'run with double quotes'
run with double quotes
+ su -c 'echo a b c' user1
a b c
+ echo 'run with single quotes'
run with single quotes
+ su -c 'echo $@' user1

$
Related Question