Home > Back-end >  How to check the error code of a command executed by "bash -c ''"?
How to check the error code of a command executed by "bash -c ''"?

Time:09-16

I had some invocation of RSYNC like in the following example. For various reasons the error code of RSYNC is required as well and retrieved using $? after the statement. AFAIK even though two commands are executed in this example, the error code should really be that of RSYNC instead of NICE. Though, I don't know if NICE forwards that code of RSYNC by design or replaces itself with RSYNC, so that only that code gets generated. Doesn't matter too much anyway, the received codes properly map to how RSYNC behaves.

/[...]/nice [...] /[...]/rsync [...]

That statement above needed to be changed to log output of RSYNC as well. From my understanding this is pretty mich like with other cases of SUDO etc., where adding shell redirection at the same level doesn't work. Instead of RSYNC, the shell redirection would cover the output of NICE in, maybe depending on how NICE actually works internally. Anyway, starting a new shall with its own specific redirection should be safe always, like in the following example:

/[...]/nice [...] bash -c "/[...]/rsync [...] > [...] 2>&1"

And here's the point: Which error code does $? right after that statement retrieve now?

Is BASH returning the error code of the last executed command or does it always return 0, as its own execution succeeded? If it forwards the error code of RSYNC, everything would be fine like with not using intermediate BASH in the past. OTOH, it might be necessary to additionally trigger BASH to exit in case of errors, possibly forwarding the last error code this way:

/[...]/nice [...] bash -c "set -o errexit ; /[...]/rsync [...] > [...] 2>&1"

I've tested the second and third example on the shell with rsync --version vs. rsync --version_, with the latter leading to an error message of RSYNC as intended. In both cases it seems that BASH properly returns the error code of RSYNC itself. Though, I couldn't find too much documentation about that behaviour, example what happens in case of multiple commands executed using -c etc.

So, how to properly check the error code of a command executed using bash -c '[...]'? Is e.g. set -o errexit necessary at all, might it even harm?

Thanks!

CodePudding user response:

The exit code of Bash is the exit code of the last command it executed.

set -e / set -o errexit does not change this. It's easy to establish through experimentation:

bash$ bash -c 'exit 17'; echo $?
17
bash$ bash -c 'set -e; bash -c "exit 17"; echo still here'; echo $?
17
bash$ bash -c 'set -e; nice -1 bash -c "exit 17"; echo still here'; echo $?
17
  • Related