Accessing an exit code outside of a su -m $USER -c "<cmd>"

8

1

The below command prints "0" or "1" correctly depending on failure or not because i put $? inside the "su" command.

sudo su -m $USER -c "./shutdown.sh &> /dev/null; echo \$?"

However, if i do this:

sudo su -m $USER -c "$BASE/bin/shutdown.sh &> /dev/null"; echo $?

it will always print "0" because the actual "su" will always succeed, even if the command portion fails.

Any idea how I can retrieve the exit code of the subshell?

Nick

Posted 2012-09-20T22:57:45.690

Reputation: 485

Answers

7

I just fixed almost exactly the same situation. Hope it still helps you, if not then perhaps others. I started from su, not sudo, but since sudo is intended to wrap a single other command, it really ought to relay su's exit code. If not, you can apply the fix below on the sudo level also.

Like you noted the main problem is that su succesfully executes it's command. The default action is then to report that it completed without any problems and so it returns exit code 0. It doesn't "know" that a non 0 exit code from a command was unexpected, or that it should do something with it. Thus the solution is quite simply to make su return the exit code of it's last command. This did it for me

su <user_x> -c '<bunch_of_commands>; exit $?'

In case sudo doesn't play nice, the whole command should be something like this (I would check this for you but I don't have sudo installed)

sudo 'su <user_x> -c \'<bunch_of_commands>; exit $?\'; exit$?'

Watch for the nesting of quotes and make sure $? doesn't get expanded, so no double quotes.

Captain Coder

Posted 2012-09-20T22:57:45.690

Reputation: 171

2

Echo the return value inside the command and access it outside by assigning the whole command to a variable (using a subshell.)

RETVAL=$(sudo su -m $USER -c "./shutdown.sh &> /dev/null; echo \$?")
echo $RETVAL

Aaron Copley

Posted 2012-09-20T22:57:45.690

Reputation: 448

0

You could always use a tmp file:

$ sudo su -m $USER -c "$BASE/bin/shutdown.sh &> /dev/null; echo \$? > /tmp/exit_code"; cat /tmp/exit_code

terdon

Posted 2012-09-20T22:57:45.690

Reputation: 45 216

Yeah, this is what I am doing right now, but I was hoping not to rely on a tmp file. – Nick – 2012-09-21T17:48:30.263

0

This works in Zsh/Bash/Bourne shells:

$ sudo su -m $USER -c "$BASE/bin/shutdown.sh &> /dev/null"
$ echo $?

I am not sure why the return code is not available when you ask for it in a one-liner, but it is available when you use more than one line to do the same thing.

zero2cx

Posted 2012-09-20T22:57:45.690

Reputation: 611

This is actually not correct. This will always return zero because the "su -m $USER -c <cmd>" will always succeed even if the actual command within it doesn't. – Nick – 2012-09-21T17:47:52.040

1@Nick -- It works here. What's your output? Try sudo su -m zero2cx -c "/bin/false &> /dev/null" but with your system username. $? should be '1'. – zero2cx – 2012-09-21T18:35:44.687

Yup, with my own username it returns "1" as expected. But I'm trying to use this to run an app via its own user and not root or any other user. – Nick – 2012-09-22T00:47:20.783

@Nick -- It should work with $ USER=appusername set as you wish. Don't user a real username, insread use your intended appusername. It should work, it does for me. – zero2cx – 2012-09-22T04:48:21.293