I put together an automatic hourly backup of selected directories using rsync and a systemd timer. It was a little bit more of a hassle than I anticipated, given my complete unfamiliarity with systemd, so I thought I’d document it for my own records and in case it’s useful to someone else on a distribution with systemd who has a similar use-case to mine.
Why a systemd timer and not cron?
In my case, mostly because I already have systemd and the timer comes with it, while I’d have to install cron. Evidently a systemd timer also has some advantages over cron such as easy debugging and flexibility. The Arch Wiki lists some benefits and caveats of using the systemd timer as a cron replacement.
Step 1: Set up the backup script
I used rsync for the backup script. While I’m not ssh-ing into an external machine and just using an external hard drive, it’s simple yet robust enough for this use-case, too. My backup script file is just a shell script that starts with lines like:
|
|
As you may know if you have some familiarity with rsync, the trailing slash on the source is significant.
Without the trailing slash, the files in the source directory are copied into a subdirectory of the destination.
This means that, in the above example, files and diretories from the Documents
and Pictures
directories are backed up to the Documents
and Pictures
directories of the external drive.
The files and directories in .config
, on the other hand, are backed up to Programs/.config
in the external drive.
This file was made executable with chmod +x
and lives in my ~/.local/bin
with the file name backup
.
Yeah, I guess it should be backup.sh
, but without the extension it’s shorter to run manually from the command line and it works.
I am told the more proper way to do this is by creating a symlink named backup
to my actual .sh file, but I don’t have a separate coding or development directory and I’m lazy lol.
Oh, and of course, to call backup in ~/.local/bin
directly from the command line I had to add ~/.local/bin
to my $PATH
, which I did with a line in .bashrc
like this:
|
|
I put ~/.local/bin
and ~/go/bin
ahead of $PATH
rather than appending them, btw, because this way my local executables take precedence over the system ones.
If there happens to be a binary called backup
in the system files, for instance, when I type backup
in the terminal I’ll be getting the backup
script I wrote.
This was another piece of advice from my dev friend, one that I actually took.
Once the backup script is tested and confirmed to be working, it’s time to set up the systemd service and timer.
Step 2: Set up the systemd service and timer
I wrote a filebackup.service
text file that consists of just the following lines:
[Unit]
Description=File backup service
[Service]
ExecStart=/home/ljwrites/.local/bin/backup
You can set the description to whatever text string you like, and ExecStart
is obviously a call to execute the backup
file I put in .local/bin
.
And here’s my filebackup.timer
file:
[Unit]
Description=Hourly backup of files
[Timer]
OnCalendar=Hourly
AccuracySec=1s
Persistent=false
Unit=filebackup.service
[Install]
WantedBy=timers.target
OnCalendar=Hourly
sets the hourly interval, and Unit
calls the filebackup.service
from above.
I have no idea if timers.target
is the best timer for this but it works.
There’s a more detailed explanation of timer types on (where else?) Stack Exchange, so check up on that if you’re interested.
According to that explanation it looks like basic.target would have worked, too.
I moved both the service and timer files to the /etc/systemd/system
directory.
Step 3: Activate the systemd timer
You can check the list of timers with:
systemctl list-timers
You can include inactive timers with the --all
flag:
systemctl list-timers --all
filebackup.timer
shouldn’t be on the list yet.
You can add it with:
sudo systemctl enable --now filebackup.timer
Check timer list again and it should be there, with the NEXT and LEFT columns set to the start of the next hour.
Update 2021/6/15: If the NEXT and LEFT columns of the backup timer show up as n/a, it may help to restart it using the following command:
sudo systemctl restart filebackup.timer
Step 4: Check if the backup ran with systemd journal
You can check if the backup timer is running on schedule with:
sudo journalctl -u filebackup.*
I’ve set this to an alias because I like the peace of mind in knowing I have regular backups of my stuff.
|
|
And that’s it!
There you have it, my file backup setup. It’s really simple and basic, but does what I need it to do. It also took me a while to get working properly because I couldn’t find specific step-by-step instructions for my particular needs. Maybe it’ll help others who have similar use-cases but are not devs.