Moving a user cron job to a systemd timer
How to replace crond entries with systemd services and timers.
23 March 2019

I have been using cron for well over a decade to schedule tasks to run when I’m not logged in. However, maintaining logs for these has been difficult and, after using systemd for a while, think I should switch to using a timer.

First, take a look at your current cron jobs.

$ crontab -l
0 * * * * offlineimap

This syncs my email every hour on the hour. For an equivalent systemd implementation we need to write a timer and a service. The timer will call the service at the scheduled time.

# $HOME/.config/systemd/user/offlineimap.service
[Unit]
Description=Local offlineimap service

[Service]
ExecStart=/usr/bin/offlineimap

[Install]
WantedBy=default.target

# $HOME/.config/systemd/user/offlinemap.service.d/01-env.conf
# There is no shell expansion here.
# Don't surround the values with quotes.

[Service]
Environment=XDG_CONFIG_HOME=/home/local/.host/config
Environment=XDG_DATA_HOME=/home/local/.host/data
Environment=XDG_RUNTIME_HOME=/home/local/.host/runtime
Environment=XDG_CACHE_HOME=/home/local/.host/cache

# $HOME/.config/systemd/user/offlineimap.timer
[Unit]
Description=Sync mail using IMAP every hour

[Timer]
OnCalendar=hourly

[Install]
WantedBy=timers.target

Now we can load these new units with “systemctl –user daemon-reload” and start them with “systemctl –user enable offlineimap.timer”.

Further reading: UNIX and Linux System Administration Handbook (5th Edition) [Amazon]