When I read this answer about $? another question comes to mind.
Is there any best practice for how to use $? in bash?
Let’s have a example:
We have a linear script and I we would like to know that all the command was executed ok.
Do you think it is ok to call a small function (let’s call it “did_it_work”),
to check the error code and break if it’s not.
#!/bin/bash
function did_it_work {
code=$1
if [ "$code" -ne "0" ]
then
echo "Error failure: code $code "
exit 1
fi
}
dir=some/path
mkdir -p $dir
did_it_work $?
cd $dir
did_it_work $?
run_some_command
did_it_work $?
This approach of course means that I have to manually solve the problem if there is any and rerun the script.
Do you think this is a good idea or is there some other best practice to do this?
/Thanks
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
One common way is:
die() {
IFS=' ' # make sure "$*" is joined with spaces
# output the arguments if any on stderr:
[ "$#" -eq 0 ] || printf '%sn' "$*" 1>&2
exit 1
}
then you use it like this:
mkdir -p some/path || die "mkdir failed with status $?"
Or if you want it to include the exit status, you could change it to:
die() {
last_exit_status=$?
IFS=' '
printf '%sn' "FATAL ERROR: $* (status $last_exit_status)" 1>&2
exit 1
}
and then using it is a bit easier:
mkdir -p some/path || die "mkdir failed"
When it fails, mkdir will likely already have issued an error message, so that second one may be seen as redundant, and you could just do:
mkdir -p some/path || exit # with the same (failing) exit status as mkdir's mkdir -p some/path || exit 1 # with exit status 1 always
(or use the first variant of die above without argument)
Just in case you haven’t seen command1 || command2 before, it runs command1, and if command1 fails, it runs command2.
So you can read it like “make the directory or die”.
Your example would look like:
mkdir -p some/path || die "mkdir failed" cd some/path || die "cd failed" some_command || die "some_command failed"
Or you can align the dies further on the right so that the main code is more obvious.
mkdir -p some/path || die "mkdir failed" cd some/path || die "cd failed" some_command || die "some_command failed"
Or on the following line when the command lines are long:
mkdir -p some/path || die "mkdir failed" cd some/path || die "cd failed" some_command || die "some_command failed"
Also, if you are going to use the name some/path multiple times, store it in a variable so you don’t have to keep typing it, and can easily change it if you need to. And when passing variable arguments to commands, make sure to use the -- option delimiter so that the argument is not taken as an option if it starts with -.
dir=some/path mkdir -p -- "$dir" || die "Cannot make $dir" cd -P -- "$dir" || die "Cannot cd to $dir" some_command || die "Cannot run some_command"
Method 2
You could rewrite your code like this:
#!/bin/bash
function try {
"<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="705430">[email protected]</a>"
code=$?
if [ $code -ne 0 ]
then
echo "$1 did not work: exit status $code"
exit 1
fi
}
try mkdir -p some/path
try cd some/path
try run_some_command
If you don’t actually need to log the error code, but just whether the command succeeded or not, you can shorten try() further like so:
function try {
if ! "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2a0e6a">[email protected]</a>"
then
echo "$1 did not work"
exit 1
fi
}
Method 3
If you really want to exit on an error and are using Bash, then you should also consider set -e. From help set:
-e Exit immediately if a command exits with a non-zero status.
This of course doesn’t give you the flexibility of a did_it_work() function, but it is an easy way to make sure your bash script stops on an error without adding lots of calls to your new function.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0