mounting usb drives at boot using udev on debian 2010 March 27 11:31
Posted by diamond in : Tech , 5 commentsI have an external 1.5TB usb hard disk that i use for backups. If i add it to /etc/fstab as normal, it will fail to mount on boot, as the usb subsystem won’t be initialized that early. This is unsatisfactory. So, here’s what i did to fix this.
- I added the drive to /etc/fstab with this line:
/dev/disk/by-label/bmopbackup1 /mnt/backup ext3 defaults,noauto 0 0
Note the noauto option (don’t mount this drive on boot), and the fsck pass number set to zero (don’t check this filesystem for errors on boot). As you can see, i labelled the external hard drive as bmopbackup1, using e2label. It just makes it a little easier to work with. - Next, i needed to check how udev can recognise my drive:
# udevadm info -q env -n /dev/disk/by-label/bmopbackup1
ID_VENDOR=WD
ID_MODEL=15EADS_External
ID_REVISION=1.75
ID_SERIAL=WD_15EADS_External_57442D574341565530323131333934-0:0
ID_SERIAL_SHORT=57442D574341565530323131333934
ID_TYPE=disk
ID_INSTANCE=0:0
ID_BUS=usb
ID_PATH=pci-0000:00:10.4-usb-0:4:1.0-scsi-0:0:0:0
ID_FS_USAGE=filesystem
ID_FS_TYPE=ext3
ID_FS_VERSION=1.0
ID_FS_UUID=d519f829-eef8-4651-9a21-70a0552ad933
ID_FS_UUID_ENC=d519f829-eef8-4651-9a21-70a0552ad933
ID_FS_LABEL=bmopbackup1
ID_FS_LABEL_ENC=bmopbackup1
ID_FS_LABEL_SAFE=bmopbackup1
As you can see, udev sets ID_FS_LABEL to bmopbackup1, so i can use that to uniquely identify the device to udev. If you don’t have a label on the drive, you could just as easily use ID_FS_UUID. - So, here’s the magic part. I created a udev rules file /etc/udev/rules.d/99-bmopbackup.rules with the following line:
SUBSYSTEMS=="block", ENV{ID_FS_LABEL}=="bmopbackup1", ACTION=="add", RUN+="/etc/scripts/bmopbackup-connected"
This tells udev that when it adds a block device with the filesystem label bmopbackup1, run the specified script. - I then created the /etc/scripts/bmopbackup-connected script:
#!/bin/bash
{
echo "Starting @ $(date)"
fsck -aC /dev/disk/by-label/bmopbackup1
ret=$?
echo "Fsck finished @ $(date) with return $ret"
if [ $ret -eq 0 ]; then
echo "Fsck succeeded, mounting"
mount /dev/disk/by-label/bmopbackup1
else
echo "Fsck failed, not mounting"
fi
} &>> "/tmp/$(basename "$0").log" &
# Has to run in background, because it blocks udev
If i didn’t want to run fsck on the drive, i could just tell udev to run mount /mnt/backup directly. However, given that this drive is used for backups, i definitely want the drive checked every boot (if i was really paranoid, i’d add the -f to fsck, to force it to run a full filesystem check if it’s marked clean). -
All of the above works fine for devices which are hotplugged. But, if a device is plugged in when the system boots (a.k.a. coldplugged), then udev finds it during boot, when it’s only using the tiny number of rules in the initramfs. Udev will see your device, not have any special rules for it, and ignore it. To fix this, I added the following to /etc/rc.local:
udevadm trigger --verbose --action=add --property-match ID_FS_LABEL=bmopbackup1
This simulates a hotplug event for the device once the system has finished booting.
If you try something similar to the above and it doesn’t seem to be working, a useful check is to see what udev thinks it should run when a given device is connected:
# udevadm test /sys/block/sdb/sdb1
This program is for debugging only, it does not run any program,
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.
...
udevtest: run: '/etc/scripts/bmopbackup-connected'
To run this test, you have to supply the sysfs path to where your device is currently connected. /dev/disk/by-label/bmopbackup1 is a symlink to /dev/sdb1, so /sys/block/sdb/sdb1 is the equivalent sysfs path.
Updated (2012-08-06): Added ACTION==”add” parameter to the udev rules file, to prevent the script from being run when the device change‘s (due to the fsck), or is removed (via physical disconnection). Also added the rc.local trick to cover coldbooting.