Search code examples
bashif-statementerror-handlingudisks

Conditional actions depending on error output


Is there a way to perform an if statement based on the error output of a command?

For example, I want to use udisksctl in a script which mounts a USB drive and then perform some action on the drive contents.

  1. The drive is not mounted: it should mount it and then perform the action.
  2. The drive is absent: it should throw an error message and exit;
  3. The drive is already mounted, it should perform the action;

Running udisksctl can have three results in this scenario:

In case 1), it runs successfully.

In the other two cases it returns an error, but:

  • In case 2), it gives me the error: Error looking up object for device ...
  • In case 3) it gives me the error: Error mounting /dev/sdb1: GDBus.Error:org.freedesktop.UDisks2.Error.AlreadyMounted: Device /dev/sdb1 is already mounted at

Is there an elegant way to make an if statement which takes different actions based on these two error messages?

Piping the error message to grep like this udisksctl mount -b /dev/disk/by-label/CRUZER 2> >(grep -i "Error looking up object for device") seems to make no difference in the output.


Solution

  • Branching on the text of error messages is brittle; the text could change between versions, or you could get messages which are similar but mean different things, or the output could change to a different language depending on the user's locale. But to do what you are asking, try

    if result=$(udiskctl mount -b /dev/disk/by-label/CRUZER 2>&1); then
      : success
    else
      rc=$?
      case $result in
        *"Error looking up object for device"*)
          echo case 2;;
        *"Error mounting /dev/sdb"*)
          echo case 3;;
        *) echo "$0: unexpected error $result" >&2
           exit $rc
           ;;
       esac
    fi
    

    The case inside the if is a bit unattractive; I suppose you could refactor this to use elif but then you'd have to refactor the capturing of the exit code from the failed command (assuming you care what the exit code was).

    You could obviously make the search strings more or less specific; I tried to keep them fairly general.