Hi everyone,
I always was sloppy with my backups and I really needed to do something about it. I bought a new Freecom HDD 500GB and what I wanted to do is quickly backup my files every time I plug the device in, and it should give me a proper notice when the backup is done.
Doesn’t sound that hard, or does it?
It became clear that I needed a little thingy called “udev”. And with big help from unutbu from ubuntuforums.org I managed to get a very nice script up and running.
First thing you have to do is to know how your system recognizes your USB drive.
I followed this great tutorial here. (Don’t bother the fstab!)
My rules look like these.
1 2 | SUBSYSTEMS=="usb", KERNEL=="sd?1", ATTRS{product}=="Freecom Network Drive", NAME="freecomHD", RUN+="/usr/bin/usb_backup.sh" |
Note that I have saved them under “/etc/udev/rules.d/81-local.rules”, because /etc/udev/rules.d/README says. It would also be safer I you select your device using UUID.
Files should be named xx-descriptive-name.rules, the xx should be
chosen first according to the following sequence points:80 rules that run programs (but do not load modules)
After adding your rule, you need to restart udev.
$ sudo /etc/init.d/udev restart
Next install libnotify-bin through synaptic. This will make it possible for us to show notifies as if it were GNOME itself
Next we’ll need to hack the script a little bit:
Place this in “/usr/local/bin/alt-notify-send”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/bin/sh user=`whoami` pids=`pgrep -u $user gnome-panel` title=$1 text=$2 timeout=$3 if [ -z "$title" ]; then echo You need to give me a title >&2 exit 1 fi if [ -z "$text" ]; then text=$title fi if [ -z "$timeout" ]; then timeout=60000 fi for pid in $pids; do # find DBUS session bus for this session DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS \ /proc/$pid/environ | sed -e 's/DBUS_SESSION_BUS_ADDRESS=//'` # use it DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS \ notify-send -u low -t $timeout "$title" "$text" done |
This is because
The reason why notify-send was not working was because notify-send uses the DBUS_SESSION_BUS_ADDRESS environment variable and that variable was not set in the shell that runs your script. This environment variable is set when you start a gnome session, but is not set when root runs a udev rule.
Moreover, one user can not send messages to another user using notify-send. So we use “su” to change root to your normal user, and we use the alt-notify-send script to find and set the DBUS_SESSION_BUS_ADDRESS before launching notify-send.
(unutbu)
Then I created a file /usr/bin/usb_backup.sh.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/bin/bash { mount_point=$(grep freecomHD /etc/mtab) attempts=1 while [ -z "$mount_point" ] && [ "$attempts" -le 50 ]; do # $mount_point has not been found # quit if this fails more than 50 times. # This should not be necessary, but it better to be safe # than have the script trapped in this loop forever for # some unforeseen reason. sleep 1 mount_point=$(grep freecomHD /etc/mtab) attempts=$(($attempts+1)) done if [ -n "$mount_point" ]; then su ruben alt-notify-send "Backup Message" "USB Backup device detected" 0 rsync -a /home/ruben/ /media/FREECOM\ HDD/ su ruben alt-notify-send "Backup Message" "Your USB Backup has completed" 0 fi } & |
Note that my user is named “ruben” and that you should replace it by your own. Also replace the the name in mount_point to the name you have given in your udev-rules.
Also note that the whole process is run in a new process (due to the “&” character). Otherwise ubuntu will try to do the backup before the mount. But it needs to be mounted before backup. This requires the little hack on top of the script
Don’t forget to make the scripts executable!
1 2 | $ sudo chmod 755 /usr/bin/usb_backup.sh $ sudo chmod 755 /usr/local/bin/alt-notify-send |
It may be a good thing to tweak your rsync a little bit, so you don’t lose too much time every time you plug in.
And that’s it! This was a little harder than I thought. But then again, it shows that you’re absolutely free to do whatever you want on ubuntu. This is why we all love our tux.
Hope this helped somebody. And stick around to read more about all sorts of stuff!
Happy coding!









Hi. Can you tell me why your script fires 14 times? Not exactly what I hoped for.
mihai
9 May 09 at 00:03
How do you mean ‘fires 14 times’?
Never noticed something like that happening.. Maybe you have several udev rules?
ruben
9 May 09 at 10:12
I only have one rule. Udev just does this, fires more instances of the script.
It happened to others too. Some attempted solutions such as writing to a text file to make only one instance survive and do the rsync but it doesn’t work perfectly.
I’m running Ubuntu 9.04 BTW.
mihai
9 May 09 at 13:18
Also running on Ubuntu 9.04. I did not notice anything like that happening, but I did not check processes either. I’m not able to check this now, as I’m not at home for a couple of days.
If this is udev running the script more than once, this may be a bug in udev. Maybe some sort of check in the beginning of the script you can check:
“ps -e | grep usb_backup”, if not empty, then exit.
Or the solution you pointed out, using some sort of lock-file should work. creating a temp file in /tmp using “touch /tmp/usb_backup_lock” and then delete it after the backup. Otherwise if file already exists, exit.
I hope this helps you.
ruben
9 May 09 at 13:33
Yes, this is what I’m using, a lock file. But two scripts still get fired sometimes. I think they get fired two fast for the first to finish writing the file.
mihai
9 May 09 at 18:02
I got the chance to check it out. No extra processes running here, sorry.
It might be interesting to file a bug report about this on launchpad.
ruben
10 May 09 at 11:17
Hi, should udev work on ubuntu 9.04? I can’t get it working. The udev rule doesn’t run the script and in /dev/ no folder is created.
whoami
13 May 09 at 18:24
I’m afraid I can’t help you with that. It seems that your description in your udev-rule doesn’t match your drive.
You should check out the link provided to write your own udev rule to match your drive.
ruben
14 May 09 at 20:03
Hello
I need to do the same, but with ANY usb device that is connected to the computer (automatically). I don’t know how to get in one variable the mount point of the lastest usb drive pluged, which I think is what I need in order to use the code you posted here.
Any suggestions?
adario
19 Nov 10 at 20:10
Hello,
I just stumbled across this post after hours of searching for a solution to exactly the problem it describes! This site should be higher in the google search results
A couple of things I’ve had to change:
1) Since Ubuntu no longer uses gnome-panel, line 4 in alt-notify-send should be pids=`pgrep -u $user compiz`. That seems to have done the trick for me.
2) I’ve had to increase the timeout value passed to alt-notify-send from 0 to about 10. When set to 0, a confirmation box appeared instead of the notification.
Thanks!
john
6 Apr 12 at 01:04