Automate backups to USB as soon as it is plugged in: Linux!

Posted On Jul-27

Simple’ were the requirements for this evening: When I plug in my USB drive into my Openstack(ubuntu) server, i want it to automatically start backing up vm-harddisks.

Well, that sounds easy. But ubuntu doesn’t always assign the same device-node to my usb drive. Sometimes its /dev/sdc1 and sometimes its /dev/sdb1 … so first order of business is to get ubuntu to assign the same device node, and mount point to my usb disk.


So after some research, i found this very straight-forward method to achieve just what i wanted. ‘udev’ is a nifty little tool that can map a device to the same device-node.

How? You can tell it some unique properties of the device, and if it matches those properties, you can tell it which device-node (or symlink to assign). And finally, we can tell it to mount the device node to a static mount-point when the device is plugged in.

  1. Find a set of attributes unique to this device
  2. Use custom udev-rules to assign a static device-node when these properties are seen
  3. Use kernel events to mount this device-node to a static mount-point

1. Find a set of attributes unique to this device

We’re looking for details about our USB drive – unique details. First lets find our current usb device-node using disk.

root@core ~# fdisk -l | grep "^/dev/"

/dev/sda1   *      122880      999423      438272   83  Linux
/dev/sda2         1001472    39061503    19030016   8e  Linux LVM
/dev/sdb1               2   488397167   244198583    b  W95 FAT32
/dev/sdd1               2   976773167   488386583    b  W95 FAT32

The USB drive I’m interested in is ‘/dev/sdd1’ . So lets find out some unique attributes to identify this same exact device every time.

There is a very good tutorial on udev rules here.  Or you can simply walk all the available properties using the command
‘ udevadm info –attribute-walk –name=/dev/sdd1’

The unique properties I picked for my device are :
SUBSYSTEM==”block”, ATTRS{serial}==”20150128002380F”

2. Creating custom udev-rules

Now, whenever the above properties match, i want my device-node to be /dev/nascopy.

So i just create a new ‘udev-rule’ under a new file /etc/udev/rules.d/99-custom.rules
( why did I use this name? See the link on udev rules above. The author has explained this in detail )

Now this file reads:

SUBSYSTEM==”block”,ATTRS{serial}==”20150128002380F”, SYMLINK+=”nascopy”

Now tail /var/log/syslog and plug in your USB drive . It will get assigned to /dev/nascopy. Unplug , and it will disappear.

 3. Auto-Mounting, and Backups

This part is easy. The same udev also listens to kernel events “add/remove” and can fire an action when the USB device is added/removed.

To identify the USB device we have to provide info about the  ENV of the device that was added/removed.

In this case, since we assigned the name ‘nascopy’, the ‘DEVLINKS’ env variable has the word ‘nascopy’ in it. So we can use that as a filter to trigger an action (namely mount the device, and kick off backups). So here is an extra line for my 99-custom.rules:

ACTION==”add”, ENV{DEVLINKS}==”nascopy“, RUN+=”/bin/mkdir /nascopy”, RUN+=”/bin/mount /dev/nascopy /nascopy”

This basically says => When a device is added , and its DEVLINKS matches “nascopy” then create a mount-point and mount it.

The full custom.rules file looks like this:

root@core ~#
root@core ~# cat /etc/udev/rules.d/80-custom.rules
SUBSYSTEM=="block",ATTRS{serial}=="20150128002380F", SYMLINK+="nascopy"
ACTION=="add", ENV{DEVLINKS}=="<em>nascopy</em>", RUN+="/bin/mkdir /nascopy", RUN+="/bin/mount /dev/nascopy /nascopy"
ACTION=="remove", ENV{DEVLINKS}=="<em>nascopy</em>", RUN+="/bin/umount /nascopy", RUN+="/bin/rmdir /nascopy"

( To get other ENV details, run “udevadm monitor –environment –udev” while plugging in the device. )

And thats it. With other RUN+ commands, you can kick off an rsync (which is incidentally what I’m doing)