How can I write a shell script that exits, if one part of it fails? For example, if the following code snippet fails, then the script should exit.
n=0
until [ $n -ge 5 ]
do
gksu *command* && break
n=$[$n+1]
sleep 3
How can I write a shell script that exits, if one part of it fails? For example, if the following code snippet fails, then the script should exit.
n=0
until [ $n -ge 5 ]
do
gksu *command* && break
n=$[$n+1]
sleep 3
One approach would be to add set -e
to the beginning of your script. That means (from help set
):
-e Exit immediately if a command exits with a non-zero status.
So if any of your commands fail, the script will exit.
Alternatively, you can add explicit exit
statements at the possible failure points:
command || exit 1
You can exit a script at any place using the keyword exit
. You can also specify an exit code in order to indicate to other programs that or how your script failed, e.g. exit 1
or exit 2
etc. (By convention, exit code 0 is for success and anything greater than 0 signifies failure; however, also by convention, exit codes above 127 are reserved for abnormal termination (e.g. by a signal)).
The generic construction to exit on failure is
if [ failure condition ]; then
exit n
fi
with suitable failure condition
and n
. But in specific scenarios you may proceed differently. Now for your case I interpret your question that if any of the five invocations of gksu
fail, then you mean to exit. One way is to use a function like this
function try_command {
for i in 1 2 3 4 5 ; do
if gksu command ; then
return 0
fi
fi
exit 1
}
and then, invoke the loop by try_command
.
There are (more) advanced or sophisticated ways of how to address your question. However, the solution above is more accessible to beginners than, say, Stephane's solution.
attempt=0
until gksu command; do
attempt=$((attempt + 1))
if [ "$attempt" -gt 5 ]; then
exit 1
fi
done
exit
exits the script unless it's called in a subshell. If that part of the script is in a subshell, for instance because it's within (...)
or $(...)
or part of a pipe-line, then it will only exit that subshell.
In that case, if you want the script to exit in addition to the subshell, then you'll need to call exit
upon that subshell exiting.
For instance, here with 2 nested levels of subshells:
(
life=hard
output=$(
echo blah
[ "$life" = easy ] || exit 1 # exit subshell
echo blih not run
) || exit # if the subshell exits with a non-zero exit status,
# exit as well with the same exit status
echo not run either
) || exit # if the subshell exits with a non-zero exit status,
# exit as well with the same exit status
It can become trickier if the subshell is part of a pipeline. bash
has a special $PIPESTATUS
array, similar to zsh
's $pipestatus
one that can help you here:
{
echo foo
exit 1
echo bar
} | wc -c
subshell_ret=${PIPESTATUS[0]}
if [ "$subshell_ret" -ne 0 ]; then
exit "$subshell_ret"
fi
Trap will perform an action upon receiving a signal.
trap "echo EXIT; exit" 0
trap "echo HUP; exit" 1
trap "echo CTL-C; exit" 2
trap "echo QUIT; exit" 3
trap "echo ERR; exit" ERR
n=0
until [ $n -ge 5 ]
do
n=$[$n+1]
echo $n
sleep 3
done
Run this and let it exit normally. It traps on signal 0.
EXIT
Run it again and interrupt with ^C. It traps on both signal 2 and signal 0.
CTL-C
EXIT
A non-zero exit status will trap on ERR
ERR
EXIT
I prefer doing it this way:
function exit_failed() {
echo ""
echo " ... batch failed !!!"
echo ""
exit 1
}
7z a $FN . || exit_failed
<call-something-else> || exit_failed
set -e
feature. It doesn't really apply here though. The OP wants to exit the script after 5 failing attempts to run the command. – Stéphane Chazelas Sep 12 '16 at 09:50set -e
is the only way I know to do that. – terdon Sep 12 '16 at 10:41set -e
issleep
(break
being a special builtin would cause the script to exit on failure in most shells, commands inif
or to the left of&&
are not affected byset -e
,n=...
could fail ifn
is read-only, but then that would exit the script withoutset -e
as well), so that interpretation sounds quite unlikely. I agree the question is poorly worded. – Stéphane Chazelas Sep 12 '16 at 10:46gksu
orcommand
also trigger it? That's what I was thinking of. – terdon Sep 12 '16 at 10:55&&
so used as a condition. – Stéphane Chazelas Sep 12 '16 at 11:07