rsnapshot nicely illustrates some of the features of systemd timers. As of Ubuntu 16.04, the rsnapshot package doesn’t ship with systemd service and timer files, so you have to set them up yourself.
Before I show how to setup rsnapshot with
systemd, I want to cover some of the
benefits of using
systemd timers instead of cron.
Cron syntax vs systemd timer syntax
systemd timer has a syntax for specifying repeating events than the old cron syntax.
Here’s how to specify a “weekly” cron job at 3 AM with the old cron syntax:
# cron syntax 0 3 * * 1
Here’s the same thing expressed in a
systemd timer file:
If you correctly guess that the right side in the systemd format represents Hour:Minute:Day, then you are well on your way to correctly guessing that the left side represents ‘Year-Month-Day’ format.
The old cron syntax looks nothing like a date and has to be memorized.
Logging and notification
A traditional well-behaved cron job produces no output unless there is an error, in which case the output will be mailed to you.
rsnapshot runs an important backup job, it’s useful to have some
detailed output about what it did, even on successful runs.
With systemd, output is sent to the systemd journal by default. You don’t hav to set up any output redirection or log rotation just to have good logging. Once set up, you can get logs for any of your rsnapshot runs with syntax like this:
journalctl -u rsnapshot@daily
If your login use in the
systemd-journald group, you also don’t have to be
root just to check out the logs. You can still get a nicely formatted email if
rsnapshot fails. More on that below.
Easy status reporting
systemd makes it easy to check on the status of your cron job. When did it run last? Was the last run a success or a failure? What were the most recent logs?. All those questions can answered with a quick check of the
systemctl status rsnapshot@daily
You don’t have to root to check that either.
Configuring systemd unit files for snapshot
Disable cron files
To avoid conflict, make sure you disable running rsnapshot via cron in
One time Setup: email-on-failure
In Ubuntu 16.04, there’s a not a built-in solution for getting email-on-mail when using systemd timers instead of cron. This is the one drawback I’ve found. However, once you set this up, you can re-use the solution for all your other systemd timers.
The following assumes you’ve already got outgoing email working on your box.
First, install a script which will mail diagnostic output for a failed systemd service ((more context](://bugs.launchpad.net/ubuntu/+source/systemd-cron/+bug/1583743)):
sudo wget -O /usr/local/bin/mail_on_failure https://raw.githubusercontent.com/systemd-cron/systemd-cron/master/src/bin/mail_on_failure.py
Next, install a service file that will be used to call this scirpt when another service fails. Name it like:
The contents would be:
[Unit] Description=status email for %I to admin [Service] Type=oneshot ExecStart=/usr/local/bin/mail_on_failure %i User=nobody Group=systemd-journal
Now for any service file that you want to send mail-on-failure, you’ll include these bits in your systemd
[Unit] # Like Cron would, send devops an email if this fails OnFailure=status-email-admin@%n.service [Service] Environment="MAILTOemail@example.com"
As you would for cron, you can customize the MAILTO environment variable to suit your needs for each service file.
rsnapshot systemd service file
systemd template file, a single file can be used to configure
rsnapshot runs for
/etc/systemd/system/rsnapshot@.service with the following contents.
[Unit] Description=rsnapshot (%I) backup # Like Cron would, send an email if this fails OnFailure=status-email-admin@%n.service [Service] Environment="MAILTOfirstname.lastname@example.org" Type=oneshot Nice=19 IOSchedulingClass=3 ExecStart=/usr/bin/rsnapshot %I
Creating rsnapshot timer files
Now you can create timers for the daily, weekly, monthly rsnapshot runs. In the example files I’ve set the
daily task to run at 5:30 AM, the weekly task at 4:30 AM and the monthly task at 3:30 AM. Adjust to suit.
[Unit] Description=rsnapshot daily backup [Timer] # Run every day at 5:30 AM Eastern Time OnCalendar=05:30 Persistent=true Unitemail@example.com [Install] WantedBy=timers.target
[Unit] Description=rsnapshot monthly backup [Timer] # Run once per month at 3:30 UTC, after daily and weekly runs OnCalendar=*-*-1 03:30:00 Persistent=true Unitfirstname.lastname@example.org [Install] WantedBy=timers.target
[Unit] Description=rsnapshot weekly backup [Timer] # Run once per week on Monday at 4:30 UTC, after daily OnCalendar=Monday *-*-* 04:30:00 Persistent=true Unitemail@example.com [Install] WantedBy=timers.target
Finally, you can enable the timer files you’ve created so that they’ll start running the next time the schedule dictates.
systemctl enable rsnapshot-daily.timer systemctl enable rsnapshot-weekly.timer systemctl enable rsnapshot-monthly.timer
If this all seems more complex that it should be for scheduling rsnapshot backups, it is. Both
rsnapshot and your OS distribution could offer better support for systemd and sending-email-on-failure with systemd. If they did, you could get benefits using systemd timers with rsnapshot by using setting your MAILTO environment and running
systemd enable for the timers you wanted to turn on.
If this appeals to you, considering communicating with the
rsnapshot project and possibly submitting a pull request to improve support here.