I have a bash script that runs three checks of 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=$?
This code works, but it feels too long and verbose. Is there any way to make this better? In particular, I am not satisfied:
- To run a command and then assign the exit code to a variable
- To use
[[ ... ]] , then collect its exit code on the next line to exit using - To explicitly compare variables with 0, as in
[[ $var -eq 0 ]] , instead of treating them as booleans
Ideally, the end result will be more readable, for example:
exit_1=( test1 ./src/ --test-1=option ) exit_2=( test2 ./src/ test-2-options ) exit_3=( test3 ./src/ -t 3 -o options )
Some things I reviewed:
Getting the error code in 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 )$?
It works and makes this bit shorter, but I have never seen anyone else use this before. Is this a reasonable / normal thing? Are there any problems with this?
Just run 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 like a bash short circuit. If test1 does not work, test2 and test3 do not start, and I want them all to start.
Error Detection and Exit Using || exit || 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 exit 1 bit is now right at the end of the line where you can skip it. Ideally, something like this would work:
exit [[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]]
Of course, this will not work, because [[ returns its output instead of an echo.
exit $( [[ $exit_1 -eq 0 && $exit_2 -eq 0 && $exit_3 -eq 0 ]] ; echo $? )
really works, but still seems awful.
Not directly related to exit-codes-as-boolean
[[ $exit_1 && $exit_2 && $exit_3 ]]
It does not do what you would hope to do. The easiest way to && together the three return codes stored in variables is to have the full $var -eq 0 && ... Of course, is there a better way?
I know that bash is not a good programming language - if you can even name it - but is there any way to make this less inconvenient?