14/05/2012

Scheduled backups to an external hard drive

After a narrowly averted data loss, I decided to schedule daily backups to an external hard drive. The scheduler of choice for this would be anacron, which runs tasks after a specified delay at startup, but only if it it hasn't run before in a specified time period (daily, weekly etc.) This is arguably better than a startup job running at every boot or a cron job running every day at a certain time regardless whether the computer is switched off.
I used unison as the backup synchronisation manager, it has both a GUI interface and an intervention-free console batch mode. Copying exceptions and permissions rules can be easily defined in profile scripts. You can't run this script in pure batch mode, as you have to tell the user to connect the external drive before starting the backup, so I used the Kdialog (zenity on Gnome/Unity) app for pop-up messages. The central script calling unison and displaying error messages:
(using http://ubuntuforums.org/showthread.php?t=1454742)
#
# Script using kdialog to prompt backup to an external hard drive
#

if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=KDE else DE=other fi
tdir=/media/<disk label>
export DISPLAY=:0.0
if [ $DE eq 'KDE' ]; then su <youruser> -c 'kdialog --yesno "Please connect the backup harddrive"'
else su <youruser> -c 'zenity --question --text "Please connect the backup harddrive"'
fi
if [ $? -eq 1 ] ; then
  if [ $DE eq 'KDE' ]; then su <youruser> -c 'kdialog --title "Warning" --msgbox "Backup aborted. On your own head be it."'
  else su <youruser> -c 'zenity --warning --text "Backup aborted. On your own head be it."'
  fi
exit 0
fi

if [ -d "$tdir" ]; then
  su <youruser> -c 'unison <profilename> -batch'
  if [ $DE eq 'KDE' ]; then su <youruser> -c 'kdialog --msgbox "Backup complete."'
  else su <youruser> -c 'zenity --info --text "Backup complete."'
  fi
exit 0
else
  if [ $DE eq 'KDE' ]; then su <youruser> -c 'kdialog --title "Warning" --msgbox "Folder ${tdir} not found. Did you connect the drive?"'
  else su <youruser> -c 'zenity --warning --text "Folder ${tdir} not found. Did you connect the drive?"'
  fi
exit 0
fi
exit 1
Save as /usr/bin/extbackup (or similar) and make it executable.
Replace expressions in brackets with what's appropriate for you. The script is executed as root in a non-graphical environment, so we need to specify a display and run executables as your user with su -c.
Create a unison profile /home/<youruser>/.unison/<profilename>.prf:
# Unison preferences file
root = <full path to source directory>
root = <full path to backup directory>
owner=false
perms=0
ignore = Name {,.}*{.backup} #excluded from backup
ignore = Name {,.}*{~}
Now for the anacron configuration /etc/anacrontab - here's part of mine:
# [...]
# These replace cron's entries
1   6   cron.daily   nice run-parts --report /etc/cron.daily
7   10   cron.weekly   nice run-parts --report /etc/cron.weekly
@monthly   15   cron.monthly nice run-parts --report /etc/cron.monthly
1   2   backup.daily   extbackup
Insert the bold line into your anacrontab, change the number 2 to something else if you don't want to back up 2 minutes after startup.

Bugs/Features: When called from a standard user terminal, the script asks for the user password a lot, thanks to all the sudo -c calls. Either remove the sudo calls for standalone use or just use unison.

Anacron debugging notes: sudo anacron -fdn [-t <alternativeanacrontab>] runs all tasks immediately and displays error messages.

No comments: