Automatic backup, triggered by connecting device
Posted: 24 Feb 2009, 18:31
This how-to describes how to start a backup when a specific USB harddisk is connected to the bubba.
This entry is for the B2 (BUBBA|two).
There is a B1 (BUBBA|server) version later on in this thread (here it is).
DISCLAIMER: You use all information found here on your own risk.
Log on to your bubba, using ssh, and become root. Then install the backup program:
Copy the following text to a file and name it /usr/local/bin/fork:
This script will make sure that our backup script detaches itself from udev, or udev would be blocked during the whole backup operation.
Make script executable by typing:
If you want, you can redirect output to a file instead of /dev/null. This way you can see any output that might be produced, which will help when looking for errors.
Next step is to find out what device to use. Since the device name can differ from time to time, depending on what order different devices are connected, we need a name that doesn't change. udev helps us with this by providing a name based on uuid. Here's how to locate it:
1) Connect your USB device.
2) Locate the device name in the kernel log:
3) Now find the uuid name linked to the device name by typing:
Create a new file, /etc/default/usb_backup, and put the following text in it, replacing the uuid with the one you got in previous step:
Now to the actual backup script. Create a new file, /usr/local/bin/usb_backup, and paste the following text to it:
Make it executable:
You can test the script from the command line by typing:The first part on the line will set ACTION to add, this is what udev will do when you connect the device. When it is disconnected, ACTION will be remove. The script will test what action is being performed, and quit if it differ from add, so we don't start a backup when device is being disconnect.
The script will backup selected folders to a directory called autobackup in the root on the USB device and it will try to maintain the directory structure.
Next step is to make a udev rule that identifies the USB device and starts the script. For this we'll use udevinfo that will show a list of attributes that identifies the device. Unfortunately, this step will differ from case to case, depending on what hardware you're using, but here's how I did it. My device was named /dev/sdb. sdb is the important part and I'll use it with udevinfo like this: You will of course replace sdb with the device name you got. Now you should get a list that look something like this (I have removed lines above and below sample):
Now that we have the attributes, we can build the udev rule. Paste the text (replacing attributes with the ones you got) into a file named /etc/udev/rules.d/010_backup.rules:
This script has only been tested on a BUBBA|two, though it shouldn't be to difficult to get it running on a BUBBA|server. One snag is that the udev is to old to support the RUN command in the udev rule (at least it is on my B1). It might be possible to upgrade udev, though I haven't tested this so I don't know what other effects this would have. Or you can wait for the upcoming new release, mentioned somewhere else (I think, or am I imagining things now). Another solution would be to skip the udev part and let a cron job look for the uuid device name. The cron job would call the backup script if device name exist or else it will quit.
Anyone that want to learn more about udev rules can read Writing udev rules.
Don't hesitate to post if you find any errors, have suggestions on how to improve it or have questions.
/Johan
EDIT: I have improved the part that waits for udev to settle.
EDIT: Added a link to the B1 version later on in this thread.
This entry is for the B2 (BUBBA|two).
There is a B1 (BUBBA|server) version later on in this thread (here it is).
DISCLAIMER: You use all information found here on your own risk.
Log on to your bubba, using ssh, and become root. Then install the backup program:
Code: Select all
aptitude install rsync
Code: Select all
#!/bin/sh
/usr/bin/nohup $@ 1>/dev/null 2>&1 </dev/null &
Make script executable by typing:
Code: Select all
chmod a+x /usr/local/bin/fork
Next step is to find out what device to use. Since the device name can differ from time to time, depending on what order different devices are connected, we need a name that doesn't change. udev helps us with this by providing a name based on uuid. Here's how to locate it:
1) Connect your USB device.
2) Locate the device name in the kernel log:
Code: Select all
tail -n 20 /var/log/kern.log
Code: Select all
ls -l /dev/disk/by-uuid
Change the paths to what ever you want to back up. If you want to play it safe, use a test path to start with, just in case something goes wrong.#
# The UUID of receiving device (eg. USB hard disk)
# This is found in /dev/disk/by-uuid
#
UUID=c7f180e1-3548-488c-956e-d8e3ba5a52ce
#
# Array of folders to backup. Separate each entry with a space and make sure to use ""
# if name contain spaces.
#
BACKUP_FOLDERS=("/etc" "/home" "/root" "/var/lib" "/var/mail" "/var/spool/cron/crontab")
#
# Should script be allowed to start when device is connected?
# 0 = start when connected; 1 = don't start when connected
#
NO_START=0
#
# At what rate should LED flash during backup. Lower value means higher frequency
#
LED_RATE=8192
Now to the actual backup script. Create a new file, /usr/local/bin/usb_backup, and paste the following text to it:
Code: Select all
#!/bin/bash
#
# A simple backup solution for a BUBBA|two.
# Written by Johan Stenarson
#
# It is expected to be run as a udev rule, therefor you need to set
# environment variable ACTION to 'add' when testing it from a shell.
# Eg:
# ACTION=add usb_backup
#
CMD=usb_backup
CONFIG=/etc/default/$CMD
### Include user settings if there are any
test -f $CONFIG && . $CONFIG
## Does settings allow script to start
if [ "$NO_START" != "0" ]; then
logger -t usb_backup "Not starting backup - edit $CONFIG and change NO_START to 0";
exit 0;
fi
### Mount point for USB device during backup
MOUNT_POINT=/tmp/backup_mount_point
### Quit immediately if this isn't an add action
if [ "${ACTION}" != "add" ]; then
exit 0;
fi
### Test if script is already running
if [ -f /var/run/$CMD.pid ]; then
PID="`cat /var/run/$CMD.pid`"
for i in `ps x|grep $CMD|sed 's/^ *\([0-9]*\).*/\1/g'`; do
if [ "$i" == "$PID" ]; then
exit 2
fi
done
# Script not running but .pid file exists, continue
fi
echo $$ >/var/run/$CMD.pid
### A fast flashing LED will indicate progress
echo $LED_RATE > /sys/devices/platform/bubbatwo/ledfreq
echo blink > /sys/devices/platform/bubbatwo/ledmode
### Give udev some time to finish
a=0
while [ ! -e /dev/disk/by-uuid/$UUID ]; do
((a++))
if ((a>20)); then
### Give up after 20 seconds/retries
logger -t usb_backup "Node hasn't been created after 20 seconds"
exit -1
fi
sleep 1
done
### Mount device by uuid
mkdir -p $MOUNT_POINT && mount /dev/disk/by-uuid/$UUID $MOUNT_POINT
for FOLDER in ${BACKUP_FOLDERS[*]}
do
DEST=`dirname "$FOLDER"`
mkdir -p "$MOUNT_POINT/autobackup$DEST"
rsync -a "$FOLDER" "$MOUNT_POINT/autobackup$DEST"
done
### We're done, clean up
umount $MOUNT_POINT && rmdir $MOUNT_POINT
rm /var/run/$CMD.pid
/etc/init.d/led_on
Code: Select all
chmod a+x /usr/local/bin/usb_backup
You can test the script from the command line by typing:
Code: Select all
ACTION=add /usr/local/bin/usb_backup
The script will backup selected folders to a directory called autobackup in the root on the USB device and it will try to maintain the directory structure.
Next step is to make a udev rule that identifies the USB device and starts the script. For this we'll use udevinfo that will show a list of attributes that identifies the device. Unfortunately, this step will differ from case to case, depending on what hardware you're using, but here's how I did it. My device was named /dev/sdb. sdb is the important part and I'll use it with udevinfo like this:
Code: Select all
udevinfo -a -p /sys/block/sdb
Now you need to pick a couple of attributes that identifies the device. Be sure to pick attributes from same section. A serial number would've been perfect, but my device didn't have one as an attribute. The list above show that third section contains a couple of attributes that identifies my hard disk, ATTRS{vendor}, ATTRS{model} and ATTRS{rev} (highlighted in text). I only have one such device so this is unique enough for me. If your list contains a serialnumber, use it. I will also use the SUBSYSTEMS="scsi" attribute........
looking at device '/devices/platform/fsl-ehci.0/usb1/1-1/1-1.1/1-1.1:1.0/host17/target17:0:0/17:0:0:0/block/sdb':
KERNEL=="sdb"
SUBSYSTEM=="block"
DRIVER==""
ATTR{dev}=="8:16"
ATTR{range}=="16"
ATTR{removable}=="0"
ATTR{size}=="490234751"
ATTR{capability}=="12"
ATTR{stat}==" 28 666 1099 240 0 0 0 0 0 188 240"
looking at parent device '/devices/platform/fsl-ehci.0/usb1/1-1/1-1.1/1-1.1:1.0/host17/target17:0:0/17:0:0:0/block':
KERNELS=="block"
SUBSYSTEMS==""
DRIVERS==""
looking at parent device '/devices/platform/fsl-ehci.0/usb1/1-1/1-1.1/1-1.1:1.0/host17/target17:0:0/17:0:0:0':
KERNELS=="17:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{device_blocked}=="0"
ATTRS{type}=="0"
ATTRS{scsi_level}=="0"
ATTRS{vendor}=="Maxtor 6"
ATTRS{model}=="L250R0 "
ATTRS{rev}=="BAJ4"
ATTRS{state}=="running"
ATTRS{timeout}=="30"
ATTRS{iocounterbits}=="32"
ATTRS{iorequest_cnt}=="0x24"
ATTRS{iodone_cnt}=="0x24"
ATTRS{ioerr_cnt}=="0x0"
ATTRS{modalias}=="scsi:t-0x00"
ATTRS{evt_media_change}=="0"
ATTRS{queue_depth}=="1"
ATTRS{queue_type}=="none"
ATTRS{max_sectors}=="240"
looking at parent device '/devices/platform/fsl-ehci.0/usb1/1-1/1-1.1/1-1.1:1.0/host17/target17:0:0':
KERNELS=="target17:0:0"
SUBSYSTEMS=="scsi"
DRIVERS==""
......
Now that we have the attributes, we can build the udev rule. Paste the text (replacing attributes with the ones you got) into a file named /etc/udev/rules.d/010_backup.rules:
That's it. You should now be able to connect the drive and the LED should start to flash. Backup will proceed and once it is finished, LED will stop blinking.SUBSYSTEM=="scsi", ATTRS{vendor}=="Maxtor 6", ATTRS{model}=="L250R0*", ATTRS{rev}=="BAJ4", RUN+="/usr/local/bin/fork /usr/local/bin/usb_backup"
This script has only been tested on a BUBBA|two, though it shouldn't be to difficult to get it running on a BUBBA|server. One snag is that the udev is to old to support the RUN command in the udev rule (at least it is on my B1). It might be possible to upgrade udev, though I haven't tested this so I don't know what other effects this would have. Or you can wait for the upcoming new release, mentioned somewhere else (I think, or am I imagining things now). Another solution would be to skip the udev part and let a cron job look for the uuid device name. The cron job would call the backup script if device name exist or else it will quit.
Anyone that want to learn more about udev rules can read Writing udev rules.
Don't hesitate to post if you find any errors, have suggestions on how to improve it or have questions.
/Johan
EDIT: I have improved the part that waits for udev to settle.
EDIT: Added a link to the B1 version later on in this thread.