Verifying Drive Availability
From LinuxServerTech
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
