# Cron Jobs with systemd.timer
Timers are systemd unit files whose name ends in `.timer` that control
`.service` files or events. Timers have the ability to be an alternate to cron.
Timers have built-in support for calendar time events, monotonic time events,
and have the ability to run asynchronously.
There are lots of flamewars against systemd; mostly introduced by people who
grew up with e. g. sysvinit scripts. Besides these flamewars systemd provides a
very well documented and very easy to use out of the box solution for many tasks
of an administrator.
At first we have to clarify a few terms and definitions. Systemd grows from
release to release and it has a lot of different concepts we have to deal with.
The first concept I have to introduce for a cron replacement with systemd is
Service files are commonly used to start and stop programs. The `systemctl` tool
provides the necessary commands to control your services, such as start, stop,
restart, reload, and so on. It is your job (or the job of the package
maintainer) to write an appropriate service file so that `systemctl` is able to
map e.g. the start command to the corresponding shell command.
Let's do a simple example. Somebody has written an awesome backupscript and he
wants that program to be executed daily. The start command for that piece of
software might be something like:
$ awesome_program start
So we have to tell systemd that command first. Don't forget to put the *full
path* of your script into `ExecStart`. Otherwise systemd is not able to find
Description=My awesome backup script
We call this file `awesome.service`. The structure of systemd service files is
self-explanatory. The `[Unit]` section is used to define some metadata such as
the description or dependencies. The `[Service]` section actually defines the
start command of our service. As we are most likely using a script which runs
and exists after finishing its tasks we have to set the Type to `oneshot`, see
Maybe I will give more information about that topic in another articles.
Now there is the question where we are supposed to put this file. This topic is
covered in detail in
At the moment we are just interested in the local configuration path when
running in system mode: `/etc/systemd/system`. So let's copy this service to
it's intended location `/etc/systemd/system/awesome.service`.
In the previous section we have covered the required steps to design a simple
systemd service which is used to start our script. Now we will add the unit
which is used to trigger the service. The timer has to be named according to the
corresponding service `awesome.timer`; we put this file in the same directory.
Description=Weekly trigger for my awesome program
The timer file is self-explanatory as well. It has three required sections:
`[Unit]`, `[Timer]` and `[Install]`.
I will now focus on the `[Timer]` section. It is used to define when the timer
should be activated. At first there is the `OnCalender` option. It understands a
few keywords such as `minutely`, `hourly`, `daily`, `monthly`, `weekly`,
`yearly`, `quarterly`, `semiannually`. If these keywords fit into your
requirements everything is fine; more fine graned control is provided by
Maybe you want to run your service every six hours. So you
have to define the `OnCalendar` option like this:
This means in detail (according to [systemd.time(7)]):
* every year (first asterisk),
* every month (second asterisk),
* every day (third asterisk)
* on 00:42:42 and repeat every 6 hours.
The repeating is defined with the slash. An OnCalender which runs every six
minutes instead would look like this:
Just for the sake of completeness, `Persistent=true` means that any missed timer
will run after bootup. It is useful to catch up on missed runs of the service
when the machine was off. It is compareable to anacron.
Last but not least there is the Install section left. This one is needed for the
most important part: enabling the timer. We do this with `systemctl enable
awesome.timer`. Installing the timer into the multi-user.target just means we
want it to be started during bootup. If you want to dive into more detail check
out the https://wiki.archlinux.org/index.php/Systemd#Targets[Arch Wiki]. As we
do not want to reboot now we also have to start the timer using
$ systemctl start awesome.timer
### Listing timers
Let's check if everything works as expected. Systemctl has a built in command to
list and inspect timers on your system.
$ systemctl list-timers
will tell you which timers have been recognized by systemd.
## Where is the user crontab?
Maybe you have wondered why you have to copy every file into system directories.
As mentioned before this is for systemd running in system mode. These services
and timers are started and enabled system wide for all users on the machine. If
you do not have sudo privileges or you just want to define your own timer you
can use systemd's user mode.
https://wiki.archlinux.org/index.php/Systemd[systemd] offers users the ability
to manage services under the user's control with a per-user systemd instance,
enabling users to start, stop, enable, and disable their own units. This is
convenient for daemons and other services that are commonly run for a single
user, such as https://wiki.archlinux.org/index.php/Mpd[mpd] or to perform
automated tasks like fetching mail. With some caveats it is even possible to
run xorg and the entire window manager from user services.
You do not have to change that much for using systemd's user mode. Assuming you
are using a recent version of systemd the user instance is started automatically
per user session. You can use the `~/.config/systemd/user` directory for your
service and timer files. For enabling, starting and listing the timer you just
have to append `--user`, e. g.:
$ systemctl --user enable awesome.timer
### Using user mode on a server
As the systemd user instance is running per user session it might become
difficult to run certain tasks automatically without an open ssh session. If you
want systemd to run your user tasks *without being logged in* then just linger
$ loginctl enable-linger $USER
Lingering a specific user keeps the systemd user instance running without an
corresponding user session. This ensures that your tasks actually run as