Reputation: 6725
What would be the best way to check the exit status in an if
statement to echo a specific output?
I'm thinking of it being:
if [ $? -eq 1 ]; then
echo "blah blah blah"
fi
The issue I am also having is that the exit
statement is before the if
statement simply because it has to have that exit code. Also, I know I'm doing something wrong since the exit would obviously exit the program.
Upvotes: 645
Views: 984471
Reputation: 31
you may use if
with your target command directly to check exit code is 0 or non-zero
if ps 123 >/dev/null ; then
echo 'process id 123 exists'
else
echo 'process id 123 not found'
fi
or use [[
for more complex expressions
# use || to ignore return value of first part in expression
if [[ $(ps 123>/dev/null ) || $? -eq 0 ]] ; then
echo "yes"
else
echo "no"
fi
Upvotes: 2
Reputation: 341
@Roland's comment on @dtk's answer is correct. If you have to deal with potentially-failing commands inside bash -e
or with set -e
then the following will allow capturing the return code and stdout no matter what, then testing return code and/or output and reacting accordingly:
some_command > output.out && ret=$? || ret=$? ; true
if [ $ret -eq 0 ] ; then
commands_if_command_succeeded
# e.g.
grep -q something output.out || echo "something missing" && exit 1
echo something is there, all good
else
commands_if_command_failed
fi
If you only want commands_if_command_failed
then change -eq
to -ne
and delete commands_if_command_succeeded
block and else
line. Or you could use $ret
in a case
statement as others have suggested.
Upvotes: 2
Reputation: 7739
I'm missing the most simple solution, which is just to use the &&
operator:
command --with parameters && echo "Command completed successfully"
-- assuming command
returns 0 on success, and non-zero on failure as Bash expects (which is kind of the opposite of many programming languages!)
The ||
operator can be used for failure:
command --with parameters || echo "Command failed"
Upvotes: 6
Reputation: 27872
This is a solution handling set -euo pipefail
gracefully:
# ...
some-command && true
SOME_COMMAND_EXIT_STATUS="$?"
# ...
#!/bin/bash
set -euo pipefail
# due to "set -e", using " ... && true" construct to avoid script from
# exiting immediately on expectable nonzero exit code.
# As per the Bash Reference Manual:
#
# "[...] The shell does not exit if the command that fails is
# [...] part of any command executed in a && or || list
# [as long as it isn't the final command in this list]"
#
# see https://www.gnu.org/software/bash/manual/html_node/Lists.html
# see "-e" at https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
some-command && true
SOME_COMMAND_EXIT_STATUS="$?"
if [[ "$SOME_COMMAND_EXIT_STATUS" == 4 ]]; then
echo "some-command exit status was 4"
else
echo "some-command exit status was unequal 4"
fi
Upvotes: 2
Reputation: 399
you can just add this if statement:
if [ $? -ne 0 ];
then
echo 'The previous command was not executed successfully';
fi
Upvotes: 18
Reputation: 109
Below test scripts below work for
if [[ $(echo -en "abc\n def" |grep -e "^abc") && ! $(echo -en "abc\n def" |grep -e "^def") ]] ; then
echo "pipe true"
else
echo "pipe false"
fi
if [[ $(echo -en "abc\n def" |grep -e "^abc") && $(echo -en "abc\n def" |grep -e "^def") ]] ; then
echo "pipe true"
else
echo "pipe false"
fi
The output is:
pipe true
pipe false
Upvotes: 1
Reputation: 978
This might only be useful in a limited set of use-cases, I use this specifically when I need to capture the output from a command and write it to a log file if the exit code reports that something went wrong.
RESULT=$(my_command_that_might_fail)
if (exit $?)
then
echo "everything went fine."
else
echo "ERROR: $RESULT" >> my_logfile.txt
fi
Upvotes: 2
Reputation: 581
Using Z shell (zsh
) you can simply use:
if [[ $(false)? -eq 1 ]]; then echo "yes" ;fi
When using Bash and set -e
is on, you can use:
false || exit_code=$?
if [[ ${exit_code} -ne 0 ]]; then echo ${exit_code}; fi
Upvotes: 14
Reputation: 21934
If you are writing a function – which is always preferred – you can propagate the error like this:
function()
{
if <command>; then
echo worked
else
return
fi
}
Now, the caller can do things like function && next
as expected! This is useful if you have a lot of things to do in the if
block, etc. (otherwise there are one-liners for this). It can easily be tested using the false
command.
Upvotes: 21
Reputation: 19460
An alternative to an explicit if
statement
Minimally:
test $? -eq 0 || echo "something bad happened"
Complete:
EXITCODE=$?
test $EXITCODE -eq 0 && echo "something good happened" || echo "something bad happened";
exit $EXITCODE
Upvotes: 105
Reputation: 13435
Note that exit codes != 0 are used to report errors. So, it's better to do:
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Error"
fi
exit $retVal
instead of
# will fail for error codes == 1
retVal=$?
if [ $retVal -eq 1 ]; then
echo "Error"
fi
exit $retVal
Upvotes: 462
Reputation: 81052
Every command that runs has an exit status.
That check is looking at the exit status of the command that finished most recently before that line runs.
If you want your script to exit when that test returns true (the previous command failed) then you put exit 1
(or whatever) inside that if
block after the echo
.
That being said, if you are running the command and are wanting to test its output, using the following is often more straightforward.
if some_command; then
echo command returned true
else
echo command returned some error
fi
Or to turn that around use !
for negation
if ! some_command; then
echo command returned some error
else
echo command returned true
fi
Note though that neither of those cares what the error code is. If you know you only care about a specific error code then you need to check $?
manually.
Upvotes: 587
Reputation: 2546
For the record, if the script is run with set -e
(or #!/bin/bash -e
) and you therefore cannot check $?
directly (since the script would terminate on any return code other than zero), but want to handle a specific code, @gboffis comment is great:
/some/command || error_code=$?
if [ "${error_code}" -eq 2 ]; then
...
Upvotes: 61
Reputation: 43109
Just to add to the helpful and detailed answer:
If you have to check the exit code explicitly, it is better to use the arithmetic operator, (( ... ))
, this way:
run_some_command
(($? != 0)) && { printf '%s\n' "Command exited with non-zero"; exit 1; }
Or, use a case
statement:
run_some_command; ec=$? # grab the exit code into a variable so that it can
# be reused later, without the fear of being overwritten
case $ec in
0) ;;
1) printf '%s\n' "Command exited with non-zero"; exit 1;;
*) do_something_else;;
esac
Related answer about error handling in Bash:
Upvotes: 37
Reputation: 532418
$?
is a parameter like any other. You can save its value to use before ultimately calling exit
.
exit_status=$?
if [ $exit_status -eq 1 ]; then
echo "blah blah blah"
fi
exit $exit_status
Upvotes: 72