We know that on Linux and Unix-like systems it is common to use crontab to create timed tasks.

On Ubuntu we use apt install mlocate to install a script file to /etc/cron.daily/mlocate, that is, to execute updatedb daily through the Cron mechanism. However, on my openSUSE, but I found no Crontab configuration, but I found that the index file was updated at zero hour every day, so who performs this timed task?

I found the following files by looking for files related to mlocate.

1
2
3
4
❯ locate "mlocate"
/etc/systemd/system/timers.target.wants/mlocate.timer
/usr/lib/systemd/system/mlocate.service
/usr/lib/systemd/system/mlocate.timer

It turns out that on the openSUSE system, the timing unit of Systemd is used for this purpose.

Then here we will focus on the Systemd timer unit.

systemd timing unit

Similar to Cron, systemd’s timing unit provides mechanisms to schedule tasks on Linux systems, compared to the Cron mechanism, others with the following features (on systems using systemd as initialization and service management).

  • Scheduled tasks can depend on other systemd services
  • Timing units can be managed using the systemctl command, similar to managing systemd services
  • In addition to Cron-like recurring real-time tasks (realtime), a non-time event-based task (monotonic) is also supported
  • Timing unit logging to systemd’s journal system, so it is easy to monitor and diagnose timing units uniformly

Similar to Cron, systemd’s timing unit provides mechanisms to schedule tasks on Linux systems, compared to the Cron mechanism, others with the following features (on systems using systemd as initialization and service management).

  • Scheduled tasks can depend on other systemd services
  • Timing units can be managed using the systemctl command, similar to managing systemd services
  • In addition to Cron-like recurring real-time tasks (realtime), a non-time event-based task (monotonic) is also supported
  • Timing unit logging to systemd’s journal system, so it is easy to monitor and diagnose uniformly

Types of systemd timed tasks

In the above feature, we mentioned that it supports two types - realtime and monotonic

  • Realtime - similar to Cron, this type of timed task is triggered by a defined absolute time, which is defined in the configuration file by the OnCalendar option
  • Monotonic - this type of timer will be triggered after a certain time by a specified event (e.g. system startup, service activation), defined in the configuration file by OnBootSec and OnUnitActiveSec, OnStartupSec options, and the timing of this type of timer is not fixed, it will be triggered after every will be reset after each system reboot

systemd timer task configuration

At the beginning of the article, when we were looking for the timed task for mlocate to update the file index, we saw that there is the file /usr/lib/systemd/system/mlocate.timer and yes, it is the systemd unit file with .timer as extension that defines the systemd timed unit.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[Unit]
Description=Daily locate database update
Documentation=man:updatedb

[Timer]
OnCalendar=daily
AccuracySec=12h
Unit=mlocate.service
Persistent=true

[Install]
WantedBy=timers.target

You can see that the file format is similar to the unit file of the systemd service, but it requires the [Timer] segment, where the following options are defined

  • OnCalendar=daily, meaning that it is triggered every day
  • AccuracySec=12h, meaning that the execution time needs to be speculated for some reason
  • Unit=mlocate.service, which specifies the task service that needs to be executed
  • Persistent=true, specifies that if the task can be executed due to shutdown, the task will be triggered immediately.

The timing unit specifies mlocate.service as the task to be triggered, which is the service defined in /usr/lib/systemd/system/mlocate.service, and that service defines the use of the updatedb command to update the file index.

For OnCalendar, the value is supported in the format DayOfWeek Year-Month-Day Hour:Minute:Second, for example

  • OnCalendar= - -* 5:00:00, specifying that it is executed at 5:00 am each day
  • OnCalendar=Fri 18:00:00, which specifies that it is executed on Friday of each month at 6:00 p.m.

Multiple OnCalendars can also be specified in a configuration file, for example

1
2
OnCalendar=Mon..Fri 10:00
OnCalendar=Sat,Sun 22:00

The above configuration then specifies execution at 10am every day from Monday to Friday, and at 10pm on both days of the weekend.

Let’s take an example of using monotonic type timed tasks in the service unit file foo.service under the directory /etc/systemd/system/.

1
2
3
4
5
[Unit]
Description="Foo shell script"

[Service]
ExecStart=/usr/local/bin/foo.sh

Also create a timing unit file foo.timer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Unit]
Description="Run foo shell script"

[Timer]
OnBootSec=5min
OnUnitActiveSec=24h
Unit=foo.service

[Install]
WantedBy=multi-user.target

Here we see that in the [Timer] paragraph, we define the following options.

  • OnBootSec=5min, which specifies that the execution of the specified service is triggered after 5 minutes of system startup.
  • OnUnitActiveSec=24h, which specifies that the service will be executed 24 hours after its activation, i.e. once a day (but the exact time of execution depends on the boot time).
  • Unit=foo.service, which specifies that the triggering task is the foo service we defined above, i.e., the execution of the foo.sh script.

Managing timer units

In the above feature, we said that the timer unit can be managed by the systemctl command, similar to managing a service unit.

  • sudo systemctl start foo.timer to start the specified timer unit.
  • sudo systemctl enable foo.timer to enable automatic activation of the timer unit (self-starting on boot).
  • sudo systemctl list-timers, list the timer units that are currently active on the system.

For example.

1
2
3
4
5
6
❯ sudo systemctl list-timers
NEXT                         LEFT                LAST                         PASSED      UNIT                         ACTIVATES
Fri 2021-12-03 17:00:00 CST  22min left          Fri 2021-12-03 16:00:03 CST  37min ago   snapper-timeline.timer       snapper-timeline.service
Sat 2021-12-04 00:00:00 CST  7h left             Fri 2021-12-03 00:00:03 CST  16h ago     logrotate.timer              logrotate.service
Sat 2021-12-04 00:00:00 CST  7h left             Fri 2021-12-03 00:00:03 CST  16h ago     mandb.timer                  mandb.service
Sat 2021-12-04 00:00:00 CST  7h left             Fri 2021-12-03 00:00:03 CST  16h ago     mlocate.timer                mlocate.service

We can also use journalctl directly to view the relevant logs, for example.

1
2
3
4
5
❯ sudo journalctl -u mlocate
-- Logs begin at Thu 2021-12-02 06:58:59 CST, end at Fri 2021-12-03 16:41:26 CST. --
Dec 03 00:00:03 linux-dev systemd[1]: Starting Update locate database...
Dec 03 00:00:03 linux-dev su[864]: (to nobody) root on none
Dec 03 00:00:06 linux-dev systemd[1]: Started Update locate database.

Also check the logs of mlocate timing units and services.

For more configuration details, you can refer to the official documentation .

Summary

If your system uses Systemd as the initialization and service management system and you want to use the features we mentioned before, then we can use systemd’s timer unit to define our timed tasks. Of course most systems still support the Crontab mechanism for timer tasks.