I have a bash script that runs three checks over my source code, and then exit 0
if all the commands succeeded, or exit 1
if any of them failed:
#!/bin/bash
test1 ./src/ --test-1=option
exit_1=$?
test2 ./src/ test-2-options
exit_2=$?
test3 ./src/ -t 3 -o options
exit_3=$?
# Exit with error if any of the above failed
[[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]]
exit $?
This code works, but it feels overly long and verbose. Is there some way this can be made nicer? Specifically I am not happy with:
- Having to run the command, and then assign the exit code to a variable
- Having to use
[[ ... ]]
, then collect its exit code on the next line to exit with - Having to explicitly compare variables to 0, as in
[[ $var -eq 0 ]]
, instead of treating them as booleans
Ideally, the end result would be something more readable like:
exit_1=( test1 ./src/ --test-1=option )
exit_2=( test2 ./src/ test-2-options )
exit_3=( test3 ./src/ -t 3 -o options )
# Exit with error if any of the above failed
exit ( $exit_1 && $exit_2 && $exit_3 )
Some things I have considered:
Getting the error code in to a variable in one line:
exit_1=$( test1 ./src/ --test-1=option )$?
exit_2=$( test2 ./src/ test-2-options )$?
exit_3=$( test3 ./src/ -t 3 -o options )$?
This works, and makes this bit shorter, but I've never seen anyone else use this before. Is this a sensible/sane thing to do? Are there any issues with this?
Just running the tests, and && them together:
test1 ./src/ --test-1=option && \
test2 ./src/ test-2-options && \
test3 ./src/ -t 3 -o options
status=$?
This does not work, as bash short circuits. If test1
fails, test2 and test3 do not run, and I want them all to run.
Detecing errors and exiting using || exit
[[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]] || exit 1
This saves one line of awkward exit codes and variables, but the important bit of exit 1
is now right at the end of the line where you can miss it. Ideally, something like this would work:
exit [[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]]
Of course, this does not work, as [[
returns its output instead of echoing it.
exit $( [[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]] ; echo $? )
does work, but still seems like a horrid cludge
Not explicitly dealing with exit-codes-as-boolean
[[ $exit_1 && $exit_2 && $exit_3 ]]
This does not do what you would hope it would do. The easiest way of && together three return codes stored in variables is with the full $var -eq 0 && ...
. Surely there is a nicer way?
I know bash is not a nice programming language - if you can even call it that - but is there any way I can make this less awkward?