I am having trouble exiting a backup script if the backup drive is not mounted.
My best attempt so far was:
findmnt $BACKUP_DRIVE >/dev/null || (
echo "Drive not found." && exit 1
)
This works reliably to execute the script if the device is mounted, but only the error message is echoed, the script does not get exited. So I tried the following which yields exectly the same results:
findmnt $BACKUP_DRIVE >/dev/null || (
echo "Drive not found."
exit 1
)
What troubles me about it is that if I replace exit 1
with echo test
in both examples above, the second test
message is echoed as expected.
I also tried to use a ! [ findmnt "$BACKUP_DRIVE" >/dev/null ]; then
statement but this is not working at all complaining about a unary operator expected
.
So I guess I have two questions, why in my first attempts the echo test
command is executed, but not the exit 1
command ? And of course, how should I approach this problem to get reliable results ?
Thanks in advance for your help.
( command )
creates another shell.
So
echo "hello" && (echo "foo" ; exit 0 ; echo "bar") && echo "world"
prints hello
, foo
, and world
, not bar
.
Yet, it doesn't exit the whole script. Only the one spawned by (...)
. So it doesn't echo bar
, because it exited the script (echo "foo" ; exit 0 ; echo "bar")
What you may do is
if findmnt "$BACKUP_DRIVE" >/dev/null
then
:
else
exit 1
fi
(One way among manys)
Another interpretation problem you have with one of your trials is about [...]
syntax.
[
is basically a version of test
program. It is supposed to be used to test some expression. For example [ "$x" = "12" ]
to test if string $x
is 12
. It is not part of the if
syntax.
if
syntax is if command; then dosomething; fi
.
command
being any command (including, but not limited to, [...]
that is just a command, like any other, with an exit code).
if
condition will be executed if command's exit code is 0.
Some experiments
# [ ... ] is just a command with an exit code
x=12
[ "$x" = "12" ]
echo $? # Echo 0 since previous command succeeded
[ "$x" = "15" ]
echo $? # Echo 1, since previous command failed
# Syntax of if is `if justACommand ...`
if ls / > /dev/null
then
echo "ls succeded"
fi
# prints `ls succeeded` since you can (usually) ls /
if ls /nonExistingFile > /dev/null
then
echo "ls succeeded"
fi
# prints nothing (but an error message from ls since I did not redirect 2>) because ls exit code was 1
So, the closest method to your 2nd trial, is simply to remove brackets. You don't want brackets here. It is a command that can tell you whether a file exist, or whether 2 strings are identical, or... (see man test
to see how it can do). You already have the command whose exit code tells you whether disk is mounted or not. It is findmnt
.
if ! findmnt "$BACKUP_DRIVE" >/dev/null ; then
exit 1
fi
And while I am at it the way to do it without if, closest to your first attempt would be
findmnt $BACKUP_DRIVE >/dev/null || { echo "Drive not found." >&2; exit 1 ;}
(don't forget the last ;
)
(The >&2
is to write error message on stderr, as suggested by Ed Morton. It is not related to why your code is not working, but well, it is indeed better to write error message on error stream)