Systemd timers as a replacement for Cron

Cron is not standard!
Most distributions treat cron as if it were a standard, but almost no two distributions actually use the same cron daemon. Debian uses Dillon’s Cron which places an emphasis on being lightweight. CentOS uses Vixie Cron for its SELinux support. Fedora, despite being in the REHL family, forked Vixie Cron to make Cronie, which is the recommended cron for Archlinux also. There are even more with their own unique use cases such as Bcron which tries to be more secure or the not-so-cronlike Anacron, which makes assumptions that the computer will be off. Some might be tempted to note that most cron daemons are mostly compatible, but there are quite a few differences between them. For instance, Debian’s Dillon’s Cron doesn’t even run the jobs with a shell or environment variables, which can easily break quite a few "standard" jobs. Beyond this, there are more specific things related to SELinux that have to be specified in order to work if Vixie Cron or Cronie are used. Due to this, we obviously need another cron implementation that satisfies everyone’s needs to become standard.Systemd Timers
Systemd is the new standard for init systems, intended to replace the aging SysV init system. Since then it has added a ton of features that start to encroach on other Linux utilities. Systemd timers are one of those features. Systemd timers are a way of running service units based on time. These timer units have quite a bit of flexibility, leading them to be a potential replacement for cron. Here we will explore some potential setups with Systemd timers, pitfalls, and how they improve on traditional cron. Traditional cron has all jobs for a user in a single file called the crontab. This has a few problems with configuration management, such as multiple services that require cron entries have to coordinate between themselves to prevent stepping on each other. Also any changes are non-trivial to implement since it can be difficult to determine which line is the old version and if the line exists at all. Systemd timers are implemented in twp files per job: one file describing the timing of the job, and one describing the actual job to be executed. The timing is in a .timer file, and the job is in a .service file. Timer files are special within systemd, but the .service files associated with them are written in the same way as any other .service file. Here is an example, really simple timer job that implements running clamscan:clamscan.timer | clamscan.service |
[Unit] Description=Run clamscan every day at 3:30AM [Timer] OnCalendar=*-*-* 03:30:00 [Install] WantedBy=timers.target | [Unit] Description=Run a clamscan scan [Service] Type=oneshot ExecStart=/usr/bin/ionice -c 3 /usr/bin/nice \ -n 19 /usr/bin/clamscan --recursive \ --infected --exclude-dir='^/sys|^/dev' / \ User=root |
Requisite Service | WantedBy Timer |
[Unit] Description=Fails when apache is not runnning Requisite=apache.service [Service] Type=oneshot ExecStart=/usr/bin/echo “Apache is running!” | [Unit] Description=Scheduled when apache is started WantedBy=apache.service [Timer] OnCalendar=*-*-* 00:00:00 [Install] WantedBy=timers.target |
A Systemd timer with memory limits |
[Unit] Description=Fails when apache is not runnning Requisite=apache.service [Service] Type=oneshot ExecStart=/usr/bin/echo “I and all my children can only use 100M of memory!” MemoryLimit=100M |