If you have a Linux-operated server, you can understand the challenges of having to continuously log into your server or desktop to run recurring tasks like system backups, health checks, and SSL certificate renewals. These tasks should be configured to run automatically.
One solution is to deploy bundled Linux utilities like cron and systemd timers to schedule these tasks to execute automatically. Cron tends to be more popular since you can set up a crontab to run jobs with just a single line of code. However, cron can sometimes be limited in functionality and difficult to troubleshoot (Top Reasons your Cron Job Isn't Running).
This is why some engineers opt for using systemd timers as a scheduling tool instead. A systemd timer typically requires three items to schedule a task: a script or command, a service file, and a timer file. What the systemd timer lacks in setup simplicity, however, it makes up for in feature-rich sophistication, flexibility to schedule events in real-time, and microsecond precision.
In this article, we'll provide a quick overview of how systemd works and demonstrate how to use systemd timers to schedule tasks effectively. At the end, we'll introduce an alternative platform called Airplane which is a developer tool that supports fully managed and serverless task scheduling.
What is systemd?
Systemd is a software suite with the basic building blocks for a Linux system. It provides an array of system components for Linux operating systems. Many engineers use systemd to manage system settings and services. In this article, we'll use systemd timers for scheduling operations.
What is a systemd timer?
Systemd timers offer the benefits of job scheduling tools like cron and anacron, allowing scheduling granularity. Similar to these other scheduling tools, systemd timers can trigger events, such as shell scripts and programs, at specified time intervals. They can be useful tools for scheduling routine jobs.
As mentioned in the introduction, a systemd timer typically requires three items to schedule a task: a script or command, a service file, and a timer file. Systemd timers have built-in support for calendar time events, monotonic time events, can assure a task is executed when the system is running again even if it was off during the expected execution time, and can run asynchronously.
Setting up systemd timers
To demonstrate systemd timers, we'll use cleanup-disk
and memory-usage-report
tasks as examples, along with the systemctl
(interact with services and timers), systemd-analyze calendar
(validate calendar time), and journalctl
(logs) commands on the following:
- Ubuntu-based operating system (OS) running on local machine
>= 20.04
- Ubuntu-based operating system (OS) running on cloud server
>= 20.04
For this demonstration, we'll run the clean-up
task on a cloud server and the memory-usage-report
task on a Linux Mint Desktop. Note that you can run both tasks on either host. By default, timers and services are in the /etc/systemd/system/
file path for Ubuntu-based distros and some others.
Cleanup script and service
Before creating a timer, you must create a clean-up
script and service. Our aim is to free up disk space taken up by log files, old install files, thumbnails, kernels, items in the trash, and disabled revisions of snap.
Note: The lines (`````) seclude the content to be pasted in the editor that appears when using "nano"-related commands. After pasting the content, press CTRL + X, then Y to save it and close the window. Neither the lines nor "CTRL + X to exit script
" should be pasted in the editor.
Open up the nano text editor and paste the commands below into cleanDisk.sh
located in the /opt
directory. Note that the /opt
directory is for installing add-on application software packages:
Then, we can make the script executable using the following command:
$ sudo chmod +x /opt/cleanDisk.sh
Using the nano editor, create and edit the cleanDisk.service
by adding 'Unit, Service, and Install sections. Note that the ExecStart=
option takes the command you want to run, which in this case, is to execute the cleanDisk.sh
bash script located in the /opt
directory. You can check out this service unit configuration documentation for more information on systemd services.
Memory usage script and service
You can adapt the memory usage script to look for instances of applications in the process monitoring command (ps aux
) that consume a lot of memory.
For instance, if you wanted to find out how much memory the firefox browser is using, scroll down and look for recurring words in the file path (Downloads/firefox).
$ ps aux | grep firefox
This can be collated into a report to show aggregate memory usage, which informs remediation. For brevity, you can use a script to automate the process.
Begin by creating the systemdFirefoxMem.sh
script in the home directory that, when run, automates the setup of the script and service file for your Firefox memory usage report.
Notice the string Downloads\/firefox
below. The backward slash (\
) is to escape the special character of forward slash (/
) which must be in the file path and makes up the unique string being searched for by the awk
command.
Make the script executable and run it:
Create a timer
There are two types of systemd timers, which can be used individually or concurrently:
- Real-time timers make use of wall clock time and use the
OnCalendar=
option in the [Timer
] section of a.timer
file to activate a calendar event the same way cron jobs do, but in this format:DOW YYYY-MM-DD HH:MM:SS
. - Monotonic timers are independent of wall clock times and time zones. You use these timers to schedule a task relative to a predefined event or varying starting point.
Moreover, these timers are not persistent and stop at shutdown or reset. Common monotonic timer options include OnBootSec=
, which refers to the time elapsed after system boot.
Now, let's create a real-time timer with the cleanDisk
project and a monotonic timer with the firefoxMem
project.
We'll begin by creating a cleanDisk.timer
file in the /etc/systemd/system
directory and include Unit, Timer, and Install sections. You’ll see the OnCalendar=
option. This means that the cleanDisk
job will run in the year 2022, weekly, every Saturday for September and October at 23:55. Change this to a current or future date of your choice.
See the systemd.timer documentation for more information on calendar event expression.
This time is stored on disk because of the Persistent=True
option. If the server is ever shut down or temporarily suspended within a set time, the job runs as soon as the server is back up to make up for the missed activity.
Also, a RandomizedDelaySec=
between 0 and 5 minutes has been set for the service to run. This accounts for unforeseen processes that could interfere within the set time.
Be sure to check if the time you choose is valid using the systemd-analyze calendar
command. For example, "Sat 2022-9,10~5 12:55:00
" never elapses because there are no Saturdays five days from the month’s end in September and October. However, "Sat 2022-9,10-* 23:55:00
" does elapse, as there’s one Saturday and Tuesday in each month, respectively.
Let's edit the firefoxMem.timer
file. Notice the OnBootSec=
option. This means the firefoxMem
job will run 10 minutes after booting up, assuming that the user has begun using the firefox app within that time.
Systemd timer launch, logs, and maintenance
Now we'll launch our timer and go over logs and maintenance. Launching the timer is easy. It only requires you to use systemd commands to enable
and start
the timer.
- Enable the timer:
$ sudo systemctl enable cleanDisk.timer
- Reload the systemd daemon to note that a timer has been enabled:
$ sudo systemctl daemon-reload
- Start the timer:
$ sudo systemctl start cleanDisk.timer
You can also check the status of the timer and the service. If the command has run multiple times, all of that will show on the screen. This is why it’s often preferred to use the journalctl follow
command to see the latest logs for the timer or service.
- View the latest logs of the service:
$ journalctl -f -u cleanDisk.service
- List systemd timers to see a table of past and next timing for your timer (optional):
$ systemctl list-timers
We can use similar commands to launch firefoxMem.timer
. To do so, we'll enable the timer, reload the systemd daemon, start the timer, and reboot our machine:
$ sudo reboot
The timer starts the service, which generates the usage report in the /tmp
directory based on the specified time after boot elapses. After rebooting, log in and try to view logs—in this case, the last six lines with the n
argument. Then, view the direct report generated in /tmp
directory with the cat
command after the timer has run.
Now we'll show you how to decommission a systemd timer. We'll do this for the cleanDisk.timers
commands "stop", "disable", and "reload daemon". We included an extra step to delete the script, service, and timer files using the rm
command. See below:
A similar process applies to the firefoxMem.timer
:
Systemd’s timers help you schedule tasks exclusively on Linux operating systems with much more precision and oversight than its popular competitor, cron. You can configure it to run on calendar dates, predefined events, or both, and you can easily trace its activity with the help of systemd
and journalctl
commands.
The drawback, however, is the complexity of the configuration. To schedule jobs efficiently, you must be well-versed in using the Linux OS and its CLI, and have knowledge of the right scripts, systemd services, and how to use timers.
Fortunately, there are other scheduling alternatives out there that could be a good fit for your use case. Airplane provides a maintenance-free alternative to systemd that's complete with permissions, audit logs, and an intuitive and secure UI.
A better alternative with Airplane Schedules
Airplane is a developer platform to quickly transform APIs, scripts, and queries into UIs and workflows for your team. In Airplane, you can build Tasks (functions that anyone on your team can execute such as SLQ queries, scripts, or wrapping around a REST call) and then configure your tasks to run on schedules. Airplane also has a feature called Views that allows you to create custom UIs for things like admin panels, customer onboarding workflows, and other internal dashboards.
Outside of ease of use, one of the biggest advantages of using Airplane to manage your scheduled tasks is that you get audit logs, permissions, notifications, an easy-to-use UI, and more all out of the box. You can also set your tasks to run on schedules or run them manually as one-offs.
If you're looking for an enterprise-grade task scheduler, you can get started with Airplane for free or reach out to the team at [email protected] 👋.
If anything in this article caught your interest, you can check out our blog for more scheduling-related content like how to start, stop, and restart cron, how to run cron in containers, creating Golang cron jobs, and more.