goat goat - 1 year ago 52
Bash Question

bash subshell command execution order with su

Normally I expect bash to execute commands in order when separated by a semicolon

eg, cmd1 executes before cmd2 in:


But I've come across a scenario where this doesn't hold true.

echo 'my password' | sudo -S su -c "echo a 1>&2 ; $(echo b 1>&2)" root

I would expect the output to be


but it's actually



Is this something to do with the c flag for the su command? It only seems to occur when I put the 2nd command in a subshell.

Note that the IO redirection isn't the culprit - I added that in only to make an easy way to demonstrate my issue. If you put different commands there, like a
, and a
, you'll see they're really executed out of order.

Answer Source
$ echo "hello $(echo world)"
hello world

$( ... ) runs the command inside and substitutes the collected output, i.e. the command above ends up running echo "hello world".


sudo -S su -c "echo a 1>&2 ; $(echo b)"

would end up running

sudo -S su -c "echo a 1>&2 ; b"

But with $(echo b 1>&2) the command writes b to stderr (and nothing to stdout), so while the shell is processing the string you see b appearing on the screen, and then the whole $( ... ) construct is replaced by nothing (because it writes nothing to stdout).

What ends up running is

sudo -S su -c "echo a 1>&2 ; " root

If all you want to do is run a command in a subshell, that's ( ... ), not $( ... ).