My name is Philipp C. Heckel and I write about nerdy things.

Script: Run rsnapshot backups only once and rollback failed backups using rsnapshot-once


Linux, Scripting, Synchronization

Script: Run rsnapshot backups only once and rollback failed backups using rsnapshot-once


I use rsnapshot to backup all of my data to my HTPC and home server (the home partition, office documents and the root file system). While rsnapshot is not as shiny as other backup tools, it is very flexible and effective: rsnapshot is based on rsync and makes hardlink-based backups (like cp -al), i.e. backups that point to the same inode on the disk if a file in consecutive backups is identical (much like SIS in deduplication).

However, rsnapshot is meant to be triggered by cronjobs and is built for always-on server machines rather than for lid-open-lid-close-type machines like laptops: That means that rsnapshot must be scheduled to run at a certain time (no retries!) and is not prone sudden system shutdowns. Furthermore, it does not detect failures and simply leaves unfinished backups as if they were complete. That in turn leads to more disk space being used for the backups, because the last complete backup is not really complete.

I wrote a little helper script to fix exactly this behavior: rsnapshot-once makes sure that (1) rsnapshot is only called if a backup is necessary (once every 24h for ‘daily’, once ever 7 days for ‘weekly’, …) even if rsnapshot-once is called multiple times, and (2) that crashed/interrupted backup runs are rolled-back before starting a new backup run.


Contents


1. What is rsnapshot-once?

rsnapshot-once is a wrapper for rsnapshot to ensure that daily, weekly and monthly tasks are run only once in the respective time period, i.e. it ensures that ‘weekly’ backups are executed only once a week, regardless how often rsnapshot-once is called.

rsnapshot-once accepts the same parameters as rsnapshot and uses the same config file. No additional configuration is needed.

So instead of running something like this:

You would rather run this:

Similarly, simply replace rsnapshot by rsnapshot-once in the crontab, if you run backups regularly as a cronjob. Instead of this:

Write this:

2. What’s the difference?

There are a couple of things that rsnapshot-once adds to the regular rsnapshot-behavior:

  • Run multiple times: For the intervals ‘daily’, ‘weekly’ and ‘monthly’, rsnapshot-once will first check the timestamp of the last successful backup (daily.0, weekly.0 or monthly.0) before running rsnapshot. So rsnapshot-once will only call rsnapshot if the timestamp of the ‘daily.0’ directory is more than 24 hours old.
  • Rollbacks of failed backups: Before running rsnapshot, rsnapshot-once checks whether the last backup was complete. If it wasn’t, the last directory (e.g. daily.0) is deleted and consecutive directories are renamed (daily.1 -> daily.0, …). rsnapshot-once uses its own pidfile to check if a previous backup run has been interrupted.
  • 15 minutes after boot/standby: To make sure that a backup is not starting right after the boot process, rsnapshot-once checks the uptime and the resume time before running rsnapshot. Only if both are greater than 15 minutes, rsnapshot is called.

3. Installation

Simply download rsnapshot-once, place it in your local bin directory (e.g. /usr/local/bin) and make it executable. If you haven’t already, install the PHP command line interpreter. Once this is done, it can be called from the command line or in cronjobs:

4. Example Usage

I use rsnapshot and rsnapshot-once for backing up the home-partition (/home), the root partition (/) and my office documents (/home/user/Office). All of them are backed up weekly and monthly, but the office documents are additionally backed up daily (because they change more often).

I set up my cronjobs to run rsnapshot-once like this:

First/any run: When rsnapshot-once is run, it writes to the same log file as rsnapshot (if defined in the config file). The output of a successful run for my daily office documents looks like this:

Duplicate run: If the same command is again right after this backup, rsnapshot will not be called, because the las successful backup was less than 24h ago:

Rollback run after interrupted backup: If the command is run after a failed or interrupted backup (e.g. due to a system shutdown), the output looks something like this:

14 Comments

  1. Oy

    Hi, looks like a perfect script for my use. But, before I have used sync_first and sync before rotating – Is this not needed with this script?



  2. lliseil

    Hi,
    A fu**ing great script, tested and adopted.
    Using rsnapshot to to do incremental backup on local station that’s not always on. rsnapshot-once plainly answers my need to get scheduled rsnapshot backups to be run, as well as to revert in case the process was interrupted (because eg storage was full). I just needed some more configuration:

    In php.ini:

    open_basedir = …:/etc/rsnapshot.conf:/var/log/rsnapshot:/PATH_to_SNAPSHOT_ROOT
    [Date]
    date.timezone = “Europe/Paris”
    date.default_latitude = NN.NNNN
    date.default_longitude = NN.NNNN

    Add full path to the executable in crontab (using cronie):

    /usr/local/bin/rsnapshot-once -c …

    Many thanks for sharing Philipp. Now what about the future? Or is it a dev-once ;-} Any chance to pull your great rsnapshot-once script on eg, Github?


  3. lliseil

    PS: forgot to say. Used to execute rsnapshot’s cmd_preexec before running the scheduled backup, eg to mount/umount the backup drive. This particular case is not as easy with rsnapshot-once, which needs the snapshot_root path to be readable before launching rsnapshot.



  4. Laurens

    How could I get this to work with rsnapshot report functionality? I would like to combine this wrapper with the reporting function to get a mail every day (once, e.g. end of day) to know how things are going. Any ideas? Maybe I have to add another cron job (daily) to pipe the logfile to rsnapshot report perl script and then pipe to mail? Will this wrapper not mess with the report?


  5. Laurens

    I’ve noticed a nasty bug in this script…

    In cron you define the “weekly” to run a couple of times a week. This screws up my weeklies.

    drwxr-xr-x 5 root root 4,0K 26 mei 20:38 weekly.0/
    drwxr-xr-x 5 root root 4,0K 25 mei 21:11 weekly.1/
    drwxr-xr-x 5 root root 4,0K 24 mei 20:38 weekly.2/
    drwxr-xr-x 5 root root 4,0K 21 mei 03:00 weekly.3/

    As you can see I have weeklies every day… that shouldn’t be right?
    I also have another cycle running for a second computer.
    drwxr-xr-x 5 root root 4,0K 2 jun 08:45 daily.0/
    drwxr-xr-x 5 root root 4,0K 1 jun 08:45 daily.1/
    drwxr-xr-x 5 root root 4,0K 31 mei 08:51 daily.2/
    drwxr-xr-x 5 root root 4,0K 30 mei 08:45 daily.3/
    drwxr-xr-x 5 root root 4,0K 29 mei 08:45 daily.4/
    drwxr-xr-x 5 root root 4,0K 28 mei 08:51 daily.5/
    drwxr-xr-x 5 root root 4,0K 26 mei 17:08 weekly.3/

    What’s with that??? Why does the weekly go to three? Isn’t it because it’s trying to cycle multiple times?



  6. Masi-O

    PHP 5.6.17 (cli) on centos 6.5

    I get this warning:

    Warning: file_put_contents( /mnt/rsnapshot/files/rsnapshot.log): failed to open stream: No such file or directory in /usr/local/bin/rsnapshot-once on line 299

    The file exists 100%.

    Any idea ?

    regards


  7. lliseil

    Have been using rsnapshot-once since my comment above to backup three boxes to an external HDD plugged in my Arch desktop (push from the desktop powered by Arch linux). No issue at all on this bleeding edge system!

    Am now switching to OpenMediaVault, a diy NAS based on Debian Wheezy. rsnapshot-once also works fine. Produces a log (and email) for each (attempted) backup, but I’ll see what I can do to lighten the “spams” burden.


  8. Demian

    Hello, I am getting the same issue as Masi-O running your script on a OMV raspberry pi system with PHP 5.4.45-0+deb7u5.
    Here is my warning message:
    PHP Warning: file_put_contents( /var/log/rsnapshot.log): failed to open stream: No such file or directory in /usr/local/bin/rsnapshot-once on line 299

    Not only does the file /var/log/rsnapshot.log exist, but if I delete it running rsnapshot-once will create a new one.

    Second issue I am experiencing: I want to run backups from a laptop that isn’t always online, so when it is offline I get an error but the backup will complete successfully. After I turn on my laptop and run rsnapshot-once again it wont rollback the backup as he sees that it was successfull (but empty). Any suggestions?


  9. Mindau

    FIXED ERROR:
    PHP Warning: file_put_contents( /path/to/backup.log): failed to open stream: No such file or directory in rsnapshot-once.php …
    Tooked 3 hours to find this bug…there is extra space by opening file_put_contents
    https://github.com/grambas/rsnapshot-once/blob/master/rsnapshot-once


  10. Jochen

    I ported your script to python and added some things like recursive config file parsing when using include_config or checking for sync_first as this present could break your rsnapshot environment when rsnapshot-once is invoked. I also added a hourly option with an optional inteval argument. Defaults to every 4 hours. You can get it on github: https://github.com/devjb/rsnapshot-scripts feel free to add improvements by pull requests. I hacked this quickly and it is far away from being really beautiful code. But it looks like it works and I needed something asap ;-)


  11. Jochen

    I ported the script to python and adjusted it to my needs. That includes for example catching of “sync_first” (not supported, but does not break things when set), nested include files and stuff like that. Grab it from Github:
    https://github.com/devjb/rsnapshot-scripts