Search code examples
bashif-statement

How to exit a bash script if a disk is not mounted


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.


Solution

  • (...)

    ( 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)