Verifying Drive Availability

From LinuxServerTech

Jump to: navigation, search

To verify drive availability in scripts under Linux, there are two things to consider: whether you have the UUID or the LABEL of the drive, or not. I ran into this problem with a script that was supposed to mount a USB drive, back up data to it, then umount the drive. When the client failed to insert the drive (or forgot to turn it off), I was copying (rsync'ing) the data onto the root partition, filled it up with predictable results. The original script looked like this:

# Wrong, do not use
#! /bin/bash
umount /mnt
mount /dev/sdb1 /mnt
START_TIME=`date`
/usr/bin/rsync --verbose \
              --times \
              --owner \
              --group \
              --ignore-times \
              --links \
              --perms \
              --recursive \
              --size-only \
              --checksum \
              --delete \
              --force \
              --numeric-ids \
              --exclude-from=/etc/rsync.exclude \
              --stats \
              /etc /root /home \
              /mnt/ \
              > /root/backup.log
echo Completed Synchronization
echo $START_TIME began >> /root/backup.log
echo `date` finished >> /root/backup.log
umount /mnt

In the above, incorrect example, there is no room for failure if the client has not inserted /dev/sdb1. You will get an error message, but nothing more. To make the script more robust and failsafe, I needed a way to see if /dev/sdb1 even existed and take appropriate action either way. This involved two new things for me, personally: determining if a drive existed and figuring out how to find the return code of a command. The first was taken care of with one of two standard packages, e2label and, even more robustly, findfs (findfs works with UUID and LABELs). In this case, I was not as interested in what the label was, just if the drive existed, and had labeled all drives on formatting, so I used e2label. Following is the corrected script.

 Correct if you don't care what the label is 
#! /bin/bash
# determine if drive exists
/sbin/e2label /dev/sdb1 &> /dev/null
if [ "$?" -ne "0" ] # drive does not exist, give error message
then
  echo Backup Aborted: Drive not found > /root/backup.log
else # drive exists, start backup
  umount /mnt
  mount /dev/sdb1 /mnt
  START_TIME=`date`
  /usr/bin/rsync --verbose \
              --times \
              --owner \
              --group \
              --ignore-times \
              --links \
              --perms \
              --recursive \
              --size-only \
              --checksum \
              --delete \
              --force \
              --numeric-ids \
              --exclude-from=/etc/rsync.exclude \
              --stats \
              /etc /root /home \
              /mnt/ \
              > /root/backup.log
  echo Completed Synchronization
  echo $START_TIME began >> /root/backup.log
  echo `date` finished >> /root/backup.log
  umount /mnt
fi
# put log where users can view it
cp /root/backup.log /home/samba/logs

Note that in this case, the first line of the actual script runs the e2label command on /dev/sdb1 (where the drives are mounted by default). If the drive does not exist, the command returns a non-zero (actually, returns a 1, but I don't depend on it). The next command checks if the return value from the previous command (e2label) returned a non-zero value, indicating failure. If it does, it echoes and error message to the log and aborts. If it does not (the else part), the script goes into the local backup routine.

To find out if a particular LABEL or UUID exists, use findfs as follows:

findfs UUID=3145e969-3a49-4848-b273-20948d484120 &> /dev/null; if [ "$?" -eq "0" ] ; then echo found it ; fi

or

findfs LABEL=BACKUP_1 &> /dev/null; if [ "$?" -eq "0" ] ; then echo found it ; fi

And, finally, to mount a particular volume label or give an error message:

DISKTOMOUNT=`findfs LABEL=Backup_1` 
if [ "$?" -eq "0" ] 
then
   mount $DISKTOMOUNT /mnt
   # do whatever
else
   echo Could not find disk Backup_1
fi

Note that mount also supports the UUID and LABEL to identify the disk to mount (via the -L and -U options, respectively), meaning the above could be rewritten:

findfs LABEL=Backup_1 &> /dev/null
if [ "$?" -eq "0" ] 
then
   mount -L Backup_1 /mnt
   # do whatever
else
   echo Could not find disk Backup_1
fi