close
close

Apre-salomemanzo

Breaking: Beyond Headlines!

5 little-known features of systemd timers
aecifo

5 little-known features of systemd timers

  • systemd timers have internal controls to prevent multiple instances from running simultaneously, thus avoiding resource conflicts.

  • Enable one second resolution in systemd timers to increase precision over the default one minute resolution.

  • Have outages reported via the support of your choice. Start timers and services immediately to make debugging easier.

Linux systemd timers have a rich and sophisticated feature set. The basic features handle the most common scenarios, but you might miss some nice features like these little-known options.

The system timer

The system timer is modern replacement for the old cron command. Both commands allow you to schedule a task or process to launch at a certain time or with a certain frequency. The advantages of systemd timers are more control, more flexibility and higher resolution than cron timers.

Based on the comments and questions I get when talking about them, systemd timers might be one of the most misunderstood parts of Linux. Even when I talk to people who prefer systemd timers, they often don’t know everything on this list.

At first glance, systemd timers may seem difficult. There is new configuration syntax to learn, which many find off-putting. And you don’t just create a single configuration file. Each timer needs two separate, but related, files.

At first glance, systemd timers may seem complicated, or only for technicians. But it’s really not that bad. It’s a shame that some people avoid them and stick to cron, because systemd timers have a lot of neat tricks up their well-stocked sleeves.

1. One instance at a time

The first advantage of systemd timers comes automatically. You don’t have to do anything to benefit from it. There are internal controls that prevent a timer from firing if a previous run of the same timer has not yet completed.

This avoids resource conflicts and avoids the type of problems that can arise if, for example, two backup jobs try to run at the same time.

Timers that do not work are not deleted. They are ready and launched once the timer is up. This is important because the sequential launch of timers is ideal. Running it unplanned concurrently may cause unexpected side effects.

2. Enable second resolution sync

With cron you can schedule tasks with a resolution of 1 minute. Now with System Timers, you can program timers to go off with a resolution of one second. In fact, you can use microsecond resolution but, outside of specialized real-time scenarios, it’s hard to imagine when you would need to use it.

But here’s the problem. Systemd timers default to a resolution of one minute. You need to enable one second resolution precision like this.

(Timer)
AccuracySec=1

3. Use monotonic events for delayed execution

systemd timers have a comprehensive and flexible set of scheduling methods.

Calendar events are triggered at a particular time, on a particular day or set of days, and at a specific time. You can have multiple time specifiers for a timer, to give you different start times on weekends and weekdays. It’s also possible to not specify a time, which really means any time of day.

Monotonic events are triggered after a specified duration following an event, such as system startup. You can also set a timer to go off at a certain time after it is activated or, surprisingly, deactivated.

To have a service run 45 seconds after PC startup, use this format:

(Timer)
OnBootSec=45 seconds

Another cool trick is to trigger the timer if the time or date is changed in the PC’s system clock.

(Timer)
OnClockChange=true

4. Manually trigger timed tasks

When developing a timer, I like to do it in stages. First, make sure that the target process you are going to launch runs as a standalone process. This means that the Linux program, script, or command you intend to launch should work as expected when you use the command in a terminal window.

Second, I create the service file and put this command in it. Finally, I create the timer file that launches the service file.

To test your timer, you can set it to go off a few minutes later and wait. This works, but if you have to do it multiple times to get things working, adjusting the OnCalendar= line each time you make a change quickly becomes tedious.

You can start your timer manually whenever you want it to run.

sudo systemctl startname-of-your.timer

This works, but you have to keep in mind that this launches your timer. But if your OnCalendar= line tells the timer to start the service on the first Wednesday of the month, you’ll have to wait for that to happen before the service is triggered.

If what you really want to test is running the service, start the service instead.

sudo systemctl startname-of-your.service

There is also a corresponding stop command.

sudo systemctl stopname-of-your.service

Note that if the RefuseManualStart or RefuseManualStop units are included in your service file and set to Yes, you will not be able to manually start or stop the service. But if you’re debugging a systemd timer you created yourself, you probably didn’t include it. If necessary, you can comment on them while you test.

5. Automatically report failing services

The MAILTO directive was one of cron’s most sophisticated features. You have provided an email address to receive notifications of errors or failures. The systemd equivalent is slightly more complicated, but it offers more flexibility. The method of notification need not be email. You can just as easily send a notification to a Slack channel, for example.

The trick is to trigger another service and have that The service initiates the process that sends the notification.

In your service file, include the OnFailure= directive and set it to the name of your error reporting service. The name of your notification service must end with an at sign @ to indicate that it is a template service.

(Unit)
OnFailure=notify-error@%n.service

Our reporting service is called [email protected]. If there is a fault and this service is called, the name of the call the service is added after the @, replacing the %n token. This name can be retrieved in [email protected] as the %i token.

Our [email protected] contains:

(Unit)
Description=Report systemd timer errors

(Service)
Type=oneshot
ExecStart=/usr/local/bin/send-to-slack.sh %i

(Install)
WantedBy=multi-user.target

When this service is triggered, the name of the calling service is accessible via the %i variable. On my machine, this is passed to a script file called send-to-slack.sh which composes the message and sends it to Slack. The ExecStart= line can point to any command, program, or script you have on your computer.

And finally

One final tip is to use the systemd-analyze tool with its calendar option to check and standardize the dates and times for use in the OnCalendar statements in your timer file.

For example, to have a timer go off at 1:15 p.m. every day, specify the time on the command in a simple format and have systemd-analyze generate the normalized version for you.

systemd-analyzecalendar 13:15
Using the systemd-analyze command to normalize a time into a standard format.Using the systemd-analyze command to normalize a time into a standard format.

Using the systemd-analyze command to normalize a time into a standard format.

The standardized format is the one to use in your timer file.