Newsgroup: it.fan.marco-ditri
Titolo: automatic backups on a removable device

These scripts allow automatically running rsnapshot[0] when the right
USB hard disk is plugged in.
If you do not want so much automation then just let
gnome-volume-manager[1] do its work and then run the last script from
the command line.
/etc/udev/rules.d/68-automount.rules:
ACTION=="add", SUBSYSTEM=="block", \
	ENV{ID_FS_USAGE}=="filesystem", ENV{ID_FS_LABEL}=="red", \
	RUN+="backup.agent $env{ID_FS_LABEL}"
/lib/udev/backup.agent:
#!/bin/sh -e
##############################################################################
wait_for_fs() {
  local fs_path="$1"
  local count="$2"
  if [ -z "$count" ]; then count=60; fi
  while ! mountpoint -q $fs_path; do
    sleep 1
    count=$(($count - 1))
    if [ $count -eq 0 ]; then
      echo "$fs_path has not been mounted after $count seconds!" 1>&2
      return 1
    fi
  done
  return 0
}
##############################################################################
do_stuff() {
  if [ -e /tmp/nobackup ]; then exit 0; fi
  wait_for_fs $FSPATH || exit 1
  nice -n 19 ionice -c 3 sh $FSPATH/doit
  rsnapshot -v diff daily.0 daily.1 | mail -s "rsnapshot diff" md
  if [ -e /tmp/noumount ]; then exit 0; fi
  pumount $FSPATH
}
##############################################################################
if [ ! -t 0 ]; then
  exec >> /var/log/backup.log 2>&1
fi
if [ "$1" ]; then
  FSNAME="$1"
else
  echo "Usage: $0 name"
  exit 1
fi
FSPATH="/media/$FSNAME"
# the script may be called multiple times due to multiple change events
# being fired by the kernel
if mountpoint -q $FSPATH; then exit 0; fi
# daemonize
do_stuff &
A while loop which waits for the file system to appear is not elegant,
but you cannot do this the right way™ with only a shell script because
it requires watching /proc/mounts using inotify(3)[2].
/media/red/doit:
#!/bin/sh -e
##############################################################################
file_older_than_days() {
  local filename="$1"
  local days="$2"
  # consider a day passed if it will end in at most 6 hours
  local more=$((60 * 60 * 6))
  local now=$(date +%s)
  local filetime=$(stat --format=%Y "$filename" 2> /dev/null || echo 0)
  local age=$(($now - $filetime))
  if [ "$age" -gt $((60 * 60 * 24 * $days - $more)) ]; then
    return 0
  else
    return 1
  fi
}
##############################################################################
RSNAPSHOT_ROOT=$(awk '/^snapshot_root[\t ]/ { print $2 }'
/etc/rsnapshot.conf)
if [ -z "$RSNAPSHOT_ROOT" ]; then
  echo "Cannot determine snapshot_root!"
  exit 1
elif [ ! -d "$RSNAPSHOT_ROOT" ]; then
  echo "snapshot_root is not a directory: $RSNAPSHOT_ROOT"
  exit 1
fi
if file_older_than_days "$RSNAPSHOT_ROOT/daily.0/" 1; then
  if file_older_than_days "$RSNAPSHOT_ROOT/weekly.0/" 14; then
    if file_older_than_days "$RSNAPSHOT_ROOT/monthly.0/" 60; then
      /usr/bin/rsnapshot monthly
    fi
    /usr/bin/rsnapshot weekly
  fi
  /usr/bin/rsnapshot daily
fi
[0] 
http://packages.debian.org/rsnapshot
[1] 
http://packages.debian.org/gnome-volume-manager
[2] 
http://en.wikipedia.org/wiki/Inotify
Permalink: 
http://blog.bofh.it/debian/id_217

 it requires watching /proc/mounts using inotify(3)[2].
  I wonder if you could use inotifywait (in the package inotify-tools)
to accomplish this?
  Daniel

to accomplish this?
That or incron, but I did not want to depend on other packages.
Also, the code would probably have been as much complex as this one.
-- 
ciao, | Those people who think they know everything
Marco | are a great annoyance to those of us who do. (Isaac Asimov)

 Also, the code would probably have been as much complex as this one.
You can't use /proc/mount with inotify...
but:
inotifywait -t 5 -e MOVED_TO  /media/
if mountpoint ...
waits for /media/.hal-mtab to be changed, or exits 5 seconds...

You can't use /proc/mount with inotify...
Sure you do, but you need a reasonably modern kernel.
