3

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?

  • 1
    Try changing those single tick quotes to double quotes. Single's inhibit the variables inside them from being expanded. – slm Jul 10 '18 at 4:37
  • @slm i did and su is getting the arguments, instead of the python script. "su: unrecognized option '--rh6'" the --rh6 option should be going to python script, not su – ealeon Jul 10 '18 at 4:40
  • What's the call to this script look like? – slm Jul 10 '18 at 4:42
  • Show (don't describe) what you did. – ctrl-alt-delor Jul 10 '18 at 5:50
  • Yes, there is a way to safely pass $@: su user -c 'command "$@"' -- argv0 "$@". (you should omit the -- on non-linux systems). See the answer here for an explanation. – mosvy Nov 4 '18 at 19:10
3

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

$
  • 1
    thank you i didnt pass in the arguments as a quoted list so su -c was trying to parse the 2nd one as its own argument – ealeon Jul 10 '18 at 4:56
  • 1
    Yeah the passing of args can be pretty tricky, glad this helped. – slm Jul 10 '18 at 4:57
  • Huh, I didn't know Linux su was so different from the BSD su. On BSD you would just do su username -c 'command with args using "$@"' su-sh "$@" – Kusalananda Jul 10 '18 at 6:15
  • 1
    @Kusalananda - yes it's very peculiar. I don't run into a lot of scenarios where I ever have to personally use it, I mainly know about it b/c of the Q&A I see here 8-). I try to do everything via sudo -u instead. – slm Jul 10 '18 at 6:17
3

You might consider passing the shell positional parameters to the su command as arguments, rather than relying on having them correctly expanded in the -c argument string.

For example:

#!/bin/sh

su testuser -c 'for arg; do echo "$0 ($(whoami)): $arg"; done' -- su "$@"

then

$ ./suscript foo "bar baz"
Password: 
su (testuser): foo
su (testuser): bar baz
-1

Encapsulating the command inside a here-doc block may help you.

#!/bin/sh

su testuser -s /bin/sh <<EOF
 add_container_host.py "$@"
EOF

You can try like below as well

su testuser -c 'add_container_host.py "$@"' -- argv0 "$@"

Apart from it su-exec is also a nice alternative.

  • May I know the reason behind negative impression on this anser ? Does this answer have any flaw ? – SkyRar Nov 9 '18 at 21:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.