Conditional actions depending on error output

210 views Asked by At

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.

2

There are 2 answers

1
tripleee On BEST ANSWER

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.

2
Alessandro Macilenti On

Thanks to @markp-fuso, this is what I got:

udtmp=$(mktemp /tmp/$(basename "$0".XXXXXXXX))

udisksctl mount -b /dev/disk/by-label/CRUZER 2> $udtmp

 if grep -i "Error looking up object for device" $udtmp ; then
     exit
 elif grep -i "GDBus.Error:org.freedesktop.UDisks2.Error.AlreadyMounted" $udtmp ; then
     do something
 fi
 
 do something else

@LMC thank you for the heads up. I think I'll be using it anyway because udiskctl works well with Thunar and mnt much less.