Why do I recommend using systemd timer instead of cronjob?
This article was last updated on: July 24, 2024 am
overview
The other day I was using Terraform + cloud-init to batch initialize my lab Linux machines. It happened to be found that some timing scenarios need to use cronjob, further understand that systemd timer can completely replace cronjob, and systemd timer has some very interesting features.
Back to the topic: Why do I recommend using systemd timer instead of cronjob? Because systemd timer has these advantages over cronjob:
- Can cover all features of CronJob
- Unified logs are collected into systemd logs
- Configuration items for more detailed time accuracy
- In addition to timed scenarios, event-based triggering is also supported
- More flexible syntax than cronjob
- Richer set of usage/O&M commands
Let’s introduce them one by one.
First of all, we familiarize ourselves with this new gadget through the timer that comes with the system.
The system comes with a timer
When Ubuntu or any systemd-based distribution is installed on a new system, it creates several timers as part of the system maintenance program in the background of any Linux host. These timers trigger events required for common maintenance tasks, such as updating system databases, cleaning temporary directories, cutting log files, and so on.
We usesystemctl status *timer
Command to list all timers on my console:
1 |
|
Each timer has at least six lines of information associated with it:
- The first line is the file name of the timer and a short description of its purpose.
- The second line shows the status of the timer, whether it was loaded, the full path to the timer unit file, and the vendor’s preset.
- The third line shows its activity status, including the date and time the timer started the activity.
- The fourth line contains the date and time when the timer is next fired, and until the trigger occursapproximatelyTime.
- The fifth line shows the name of the event or service triggered by the timer.
- Some, but not all, systemd unit files have pointers to related documents. As above
Docs: man:fstrim
- The last line is the log entry for the most recent instance of the service triggered by the timer.
Create a timer
One advantage: Unified logs are collected into systemd logs
To learn about the timer faster, we created our own service unit and timer unit to trigger.
The specific purpose: Tailscale is updated regularly every week.
First, create the tailscale update service, as follows:
1 |
|
Then, create a tailscale update timer, as follows:
1 |
|
Finally, enable the timer:
1 |
|
So that’s fine, but for demonstration, execute:systemctl start tailscale-weekly-update.service
Run it manually once.
The output is integrated directly into the systemd log and can be passed through journalctl
View: (contains logs of manual execution, and logs of subsequent automatic periodic executions)
1 |
|
As shown in the above log, it is convenient to check the status of the timer and service.
In terms of logging, you don’t need to do anything special to make ittailscale-weekly-update.service
unitExecStart
of the triggerSTDOUT
Stored in logs. This is all part of running the service with systemd.
Systemd timer time precision
One of the advantages: more detailed configuration items for time accuracy
From the above log, if you look closely, the timer will not be there:00
It is accurate in seconds, not even within one minute of the previous instance. This is intentional, but its default configuration can be overridden if necessary.
The reason for this behavior is to prevent multiple services from being triggered at exactly the same time. For example, you can use time specifications such as weekly, daily, and so on. These shortcuts are defined to fire at 00:00:00 on the day they are triggered. When multiple timers are specified in this way, it is likely that they will attempt to start at the same time.
The systemd timer is intentionally designed to trigger randomly for a specified time to prevent simultaneous triggering. They trigger semi-randomly within a time window. according tosystemd.timer
Manual, this trigger time remains in a stable position relative to all other defined timer units.
Most of the time, this probabilistic trigger time is no problem. When tasks such as scheduled backups run, as long as they run during non-business hours, there is no problem. A system administrator can choose a definite start time, such as 01:05:00 in the typical CronJob specification, to not conflict with other tasks, but there is a wide range of time values to achieve this. One-minute randomness in startup time is usually irrelevant.
However, for some tasks, precise trigger times are an absolute requirement. For these tasks, you can do so by using the timer unit file Timer
The section adds such a configuration to specify higher trigger time span accuracy (e.g. accuracy within one microsecond):
1 |
|
The time span can be used to specify the desired precision and define the time span for repeatability or one-time events. It can recognize the following units:
- usec, us, µs
- msec, ms
- seconds, second, sec, s
- minutes, minute, min, m
- hours, hour, hr, h
- days, day, d
- weeks, week, w
- months, month, M (defined as 30.44 days)
- years, year, y (defined as 365.25 days)
/usr/lib/systemd/system
All default timers specify a larger range of precision, because precise timing is not critical. Take a look at some of the specifications in the timer created by the system:
1 |
|
Timer type
One of the advantages: In addition to timing scenarios, event-based triggering is also supported
Systemd Timer has other features that cron does not have, and cron is only triggered at a specific, repeated, real-time date and time. However, a timer can be configured to trigger after the system starts, or after startup, or at a specific time after a defined service unit is activated. These are calledMonotonicity timer。 Monotony refers to a continuously increasing count or sequence. These timers are not persistent because they are reset after each startup.
Table 1 lists the monotonous timers and a short definition of each timer, as well as the “OnCalendar” timer, which is not monotonic and is used to specify future times, which may or may not be repeated.
| Timer | Monotonicity | definition |
| ----- | ------------ | ---------- ||
| OnActiveSec=
| X | This defines a timer relative to the moment the timer is activated. |
| OnBootSec=
| X | This defines a timer relative to the machine startup time. |
| OnStartupSec=
| X | This defines a timer relative to the time when the Service Manager first started. For system timer units, this is the same as OnBootSec=
Very similar, because the System Services Manager usually starts very early at startup. It is primarily useful when configuring cells that run in each User Services Manager, because the User Services Manager is generally started only at first logon, not at startup |
| OnUnitActiveSec=
| X | This defines the time when the timer to be activated was last activated relative to the time to be activated. |
| OnUnitInactiveSec=
| X | This defines a timer relative to when the timer to be activated was last deactivated. |
| OnCalendar=
| | This defines a real-time timer with a calendar event expression. For more information about the syntax of calendar event expressions, see systemd.time(7)
。 Otherwise, its semantics are the same as OnActiveSec=
Similar to related settings. This timer is most like those timers used with cron services. |
Table 1: Systemd Timer Definitions
The monotonic timer time span can be used with the previous mentionedAccuracySec
statements have the same shortcut names, but systemd normalizes these names to seconds. For example, you might want to specify a timer that triggers an event 5 days after the system starts, something like this: OnBootSec=5d
。 If the host is in2020-06-15 09:45:27
Start, timer will be2020-06-20 09:45:27
or trigger within one minute of the future.
Calendar event definition
One advantage: more flexible syntax than cronjob
The Calendar event definition is the key part that triggers the timer at the desired repeat time. Take a look firstOnCalendar
Some of the specifications used in the setup.
Systemd and its timer use different time and date specifications than those used in crontab. It’s more than crontabflexible, allowed toat
The way the command obfuscates the date and time.
useOnCalendar=
The basic format of systemdtimer isDOW YYYY-MM-DD HH:MM:SS
。 DOW (day of the week) is optional, and other fields can use an asterisk (*) to match any value at that location. All calendar time forms are converted to normalized forms. If no time is specified, it is assumed to be 00:00:00. If no date is specified but a time is specified, then the next match may be today or tomorrow, depending on the current time. Names or numbers can be used for months and weeks. You can specify a comma-separated list of each unit. The unit range can be used between the start and end values...
to specify.
There are several interesting options for specifying dates. The tilde (~) can be used to specify the last day of the month or the specified number of days before the last day of the month. “/” can be used to specify the day of the week as a modifier.
Here are some inOnCalendar
Examples of typical time specifications used in statements:
Calendar event definition | Description |
---|---|
DOW YYYY-MM-DD HH:MM:SS |
|
*-*-* 00:15:30 |
Every day of each month of the year, 15 minutes and 30 seconds after midnight. |
Weekly |
Every Monday at 00:00:00 |
Mon *-*-* 00:00:00 |
Same as weekly |
Mon |
Same as weekly |
Wed 2020-*-* |
Every Wednesday in 2020, 00:00:00 |
Mon..Fri 2021-*-* |
00:00:00 |
2023-6,7,8-1,15 01:15:00 |
1st and 15th June, July and August 2023 01:15:00 AM |
Mon *-05~03 |
The next Monday in May of any year is also the third day at the end of the month. |
Mon..Fri *-08~04 |
The 4th day before the end of August in any year, or the end of August if that day is also a working day. |
*-05~03/2 |
The third day from the end of May and two days later. It is repeated every year. Note that this expression uses (~). |
*-05-03/2 |
The third day in May and then every other day for the rest of May. Repeat once a year. Note that this expression uses a dash (-). |
Table 2: ExamplesOnCalendar
Event definition
Test the calendar definition
One advantage: a richer set of usage/operation and maintenance commands
systemd provides a good tool to validate and check the calendar time event specification in the timer.systemd-analyze calendar
The tool parses a calendar time event specification and provides a normalized form as well as other interesting information, such as the date and time of the next “elapse” (i.e. match) and the approximate time before the trigger time is reached.
First, look at a date in the future that has no time:
1 |
|
Now add a time. In this example, the date and time are analyzed separately as unrelated entities:
1 |
|
To parse dates and times as a unit, enclose them in quotation marks.
1 |
|
Now test the entries in Table 2. Choose a complex one:
1 |
|
Let’s look at an example where we list the next five execution times of the timestamp expression:
1 |
|
This should give you enough information to start testing yoursOnCalendar
Time specification.
summary
Systemd Timer can be used to perform the same types of tasks as cron tools, but provides more flexibility in terms of calendar and monotonous timing specifications that trigger events.
In addition, the advantages of systemd timer include:
- Unified logs are collected into systemd logs
- Configuration items for more detailed time accuracy
- Richer set of usage/O&M commands
Try migrating your cronjob to systemd timer~ 😛😛😛
Resources
- Use systemd timers instead of cronjobs
- Fedora’s Systemd guide
- Fedora’s systemd cheat sheet