Systemd has been offering timers for a while, and timers replace cron functionality, which is worth checking out.

Systemd has been offering timers for some time, and timers replace cron functionality, which is worth taking a look at. This article shows you how to use timers in Systemd to run tasks once the system starts up and then again. This is not a comprehensive discussion of Systemd, just an introduction to the feature.

## Quick review: Cron, Anacron, and Systemd

Cron can run a task on a granular schedule ranging from minutes to months or more. It is relatively simple to set up, requiring only a configuration file. Although the configuration process is somewhat esoteric, it can also be used by general users.

However, if your system is not running at the time it needs to be running, cron will fail.

Anacron overcomes the “system is not running” problem. It ensures that the task will be executed when your system starts up again. Although it is intended for use by administrators, some systems allow ordinary users to access Anacron.

However, anacron should not be performed less frequently than once a day.

Both Cron and Anacron have problems with execution context consistency. It is important to note that the environment in effect when the task is run is exactly the same as the environment used during the test. You must provide the same shell, environment variables, and paths. This means that testing and debugging can sometimes be difficult.

Systemd timers offer the benefits of both Cron and Anacron, allowing scheduling to minute granularity. Ensure that tasks are executed when the system is running again, even if the system is down for the expected execution time. It is available to all users. You can test and debug the execution in the environment in which it will be run.

However, its configuration is more complex and requires at least two configuration files.

If your Cron and Anacron configurations work well for you, there’s probably no reason to change. But Systemd is at least worth investigating because it can simplify any current cron/ Anacron way of working.

configuration

At least two files are required to run the systemd timer function. The two are timer unit and Service unit. The “actions” are not just simple commands, you need a “job” file or script to perform the necessary functions.

The timer unit file defines the schedule table, while the service unit file defines the tasks to execute. Refer to the.timer unit provided in man Systemd. timer for more details. Details of the service unit can be found in man Systemd.service.

Unit files are stored in several locations (listed on the man pages). However, for the average user, the easiest location to find is probably ~/.config/systemd/user. Notice that the user here is the string user.

The sample

This example is a simple example of creating a user-scheduled job instead of a system-scheduled job running as root. It prints messages, dates, and times to a file.

1. Start by creating a shell script to execute the task. Create it in your local bin directory, such as ~/bin/schedule-test.sh.

Create file:

touch ~/bin/schedule-test.sh
Copy the code

Then add the following to the file you just created:

#! /bin/sh echo "This is only a test: $(date)" >> "$HOME/schedule-test-output.txt"Copy the code

Remember to grant your shell script execution permission.

2. Create the.service unit to invoke the above script. Create directories and files in the following locations:

. ~ / config/systemd/user/schedule - test. Service:  [Unit] Description=A job to test the systemd scheduler [Service] Type=simple ExecStart=/home/<user>/bin/schedule-test.sh [Install] WantedBy=default.targetCopy the code

Note that it should be your home directory address, but the user in the unit file pathname is actually the string user.

ExecStart should provide an absolute address with no variables. The exception is that for user unit files, you can replace $HOME with %h. In other words, you can use:

ExecStart=%h/bin/schedule-test.sh This is only for user unit files and not for system services because %h always returns /root when running in a system environment. Other special symbols can be found in the SPECIFIERS of man Systemd. unit. Because it is beyond the scope of this article, that is all we need to know about special symbols for now.

3. Create a.timer unit file that actually schedules the.service unit file you created. Create it in the same location as the.service unit file:

~/.config/systemd/user/schedule-test.timer
Copy the code

Note that file names differ only in extensions, such as.service and.timer.

[Unit]
Description=Schedule a message every 1 minute
RefuseManualStart=no  # Allow manual starts
RefuseManualStop=no   # Allow manual stops
[Timer]
#Execute job if it missed a run due to machine being off
Persistent=true
#Run 120 seconds after boot for the first time
OnBootSec=120
#Run every 1 minute thereafter
OnUnitActiveSec=60
#File describing job to execute
Unit=schedule-test.service
[Install]
WantedBy=timers.target
Copy the code

Notice that the.timer unit file uses OnUnitActiveSec to specify the schedule table. The OnCalendar option is more flexible. Such as:

# run on the minute of every minute every hour of every day
 OnCalendar=*-*-* *:*:00
# run on the hour of every hour of every day
 OnCalendar=*-*-* *:00:00
# run every day
 OnCalendar=*-*-* 00:00:00
# run 11:12:13 of the first or fifth day of any month of the year
# 2012, but only if that day is a Thursday or Friday
 OnCalendar=Thu,Fri 2012-*-1,5 11:12:13
Copy the code

See here for more information on OnCalendar.

4. All the pieces are in place, but you should test them to make sure everything works. First, enable the user service:

$systemctl –user enable schedule-test.service This will result in output similar to the following:

Created symlink/home / < user > / config/systemd/user/default target. Wants/schedule - test. And the service /home/<user>/.config/systemd/user/schedule-test.service.Copy the code

Now execute the test:

$ systemctl --user start schedule-test.service
Copy the code

Check your output file ($HOME/schedule-test-output.txt) to make sure your script works properly. There should be only one entry because we haven’t started the timer yet. Debug as necessary. If you need to change the.service unit file rather than the shell script it calls, don’t forget to enable the service again.

5. Once the job is running properly, schedule the job in real time by enabling and starting the user timer for the service:

$ systemctl --user enable schedule-test.timer
$ systemctl --user start schedule-test.timer
Copy the code

Note that you already started and enabled the service in Step 4 above, so you only need to enable and start the timer for it.

The enable command produces the following output:

Created symlink/home / < user > / config/systemd/user/timers. Target. Wants/schedule - test. The timer - > /home/<user>/.config/systemd/user/schedule-test.timer.Copy the code

The start command will simply return the command line interface prompt.

Other operating

You can check and monitor services. The first command below is especially useful if you receive an error from a system service:

$ systemctl --user status schedule-test
$ systemctl --user list-unit-files
Copy the code

Manually stop the service:

$ systemctl --user stop schedule-test.service
Copy the code

Permanently stop and disable timers and services, reload daemon configuration and reset any failure notifications:

$ systemctl --user stop schedule-test.timer
$ systemctl --user disable schedule-test.timer
$ systemctl --user stop schedule-test.service
$ systemctl --user disable schedule-test.service
$ systemctl --user daemon-reload
$ systemctl --user reset-failed
Copy the code

conclusion

This article starts with systemd timers, but systemd goes much further than that. This article is just to give you a foundation.