# Understanding Systemd Timers

[Systemd](https://karlygash-yakiyayeva.dev/understanding-systemd-services) is a software suite that provides a standard process for controlling what programs run when a Linux system boots up. It starts the core programs running and a journal of system activity, the network stack, a cron-style job scheduler, user logins, and many other jobs.

[Systemd timers](https://silentlad.com/how-to-use-systemd-timers-(cronjob-alternative)) are a part of this `systmed` suite and they enable us to schedule tasks to be executed at specified times or intervals, similar to [cron jobs](https://karlygash-yakiyayeva.dev/scheduling-tasks-with-cron) but with more features and tight integration with the rest of the `systemd` ecosystem.

## Systemd Timers or Cron Jobs

1. Cron is more of a stand-alone thing whereas `systemd` timers are part of `systemd`. Therefore `systemd` timers can be used only on distributions with `systemd` systems while cron jobs can be used on distributions either with `systemd` systems or `non-systemd` systems.
    
2. Systemd timers have additional features such as support for complex calendar-based events, built-in support for catching up on missed jobs, a built-in mechanism for dependency management or condition checks before job execution, and integration with `systemd’s` journal which provides centralized and unified logging etc.
    
3. Additional features of `systemd` timers come with added complexity. Therefore, `systemd` timers are a bit more involved meaning more to learn while cron jobs are much simpler to understand and implement.
    

Which one to use depends on the complexity of the task and which of the two solutions is a better fit for your project on a case-by-case basis.

## Components of Systemd Timers

To create a `systemd` timer two files are required: a `.timer` file to schedule the task and a `.service` file for the task.

* **Timer units** are the actual timer definitions. They define when and how often a task should be executed. The timer units have a `.timer` extension and are typically stored in the `/etc/systemd/system` directory. An example of `weather-report.timer` unit file is given below.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1713041691854/74cd540c-7718-4ae9-b061-7ec9ca8ac7ac.png align="center")
    
* **Service units** are the tasks that are executed when the timer is triggered. Service units have a `.service` extension and are typically stored in the `/etc/systemd/system` directory. An example of `weather-report.service` unit file is provided below.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1713041306173/4127918f-ae0e-42f0-a7b7-5c8208c87380.png align="center")
    

When you have a `.service` file with the same name as the `.timer` file in the directory, with the only difference being the file extension, `systemd` automatically considers them to be related. Usually, for each timer, there is a corresponding service file that gets executed when the timer triggers.

## Types of Timers

* **Real-time timers** are based on the actual real-world clock time. They can be set to trigger at specific times, such as "every day at 2:00 AM".
    
* **Monotonic timers** are based on a timer relative to a certain point, such as "15 minutes after boot".
    

## Hands-on Exercise Overview

Understanding `systemd` timers involve knowing how to create and manage them. This hands-on exercise shows how to create a `systemd` timer that will run the `wall` command automatically on a specific schedule.

## Hands-on Exercise

1. Create a new `weather-report.service` unit file:
    
    ```bash
    sudo vim /etc/systemd/system/weather-report.service
    ```
    
2. Copy and paste the following code into the file and save it:
    
    ```bash
    [Unit]
    Description=Weather Report Service
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    ExecStart=/bin/sh -c 'sudo wall $(curl wttr.in?format=3)'
    
    [Install]
    WantedBy=default.target
    ```
    
    This simple file executes the `wall` command, which stands for "write to all". The `wall` command sends a message to all users currently logged into the system and the message is supposed to be the output of `curl wttr.in?format=3`, which queries the `wttr.in` service for weather information in a brief format. This can be particularly useful for system administrators who need to notify users about system maintenance, reboots, or other important events.
    
3. Refresh `systemd` so that it’s aware of the fact we added a new service file:
    
    ```bash
    sudo systemctl daemon-reload
    ```
    
4. Now, when we want to send a weather report to every user on the system, all we need to do is start the `systemd` service for it:
    
    ```bash
    sudo systemctl start weather-report.service
    ```
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1713256851445/83d0ff87-2a36-4225-a647-849b9905c812.png align="center")
    
5. Create a new `weather-report.timer` unit file the type of which will be a timer:
    
    ```bash
    sudo vim /etc/systemd/system/weather-report.timer
    ```
    
6. Copy and paste the following code into the file and save it:
    
    ```bash
    [Unit]
    Description=Weather Report Service
    
    [Timer]
    OnCalendar=Mon..Fri 08:32
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    ```
    
    Under the timer section, we have `OnCalendar` here. We’re giving it a range starting with Monday and ending with Friday. Also, we’re setting it for 08:32 am, which means the timer will trigger `weather-report.service` file every weekday at 08:32 am.
    
    If the server is down for any reason the timer won’t trigger. Enabling the `Persistent=true` option, allows the task to run once the server starts up next in case the `OnCalendar` time is missed.
    
    <div data-node-type="callout">
    <div data-node-type="callout-emoji">💡</div>
    <div data-node-type="callout-text">The timer will look for a file name that’s the same as its own but with a <code>.service</code> extension instead of a <code>.timer</code> extension. Therefore we don’t tell the timer which service file to start, it already knows what it is looking for. All we have to do is match the naming scheme.</div>
    </div>
    
    In the install section, targets are another type of unit file, and when you link them like this, the current file will inherit specific characteristics from the target.
    
7. Refresh `systemd` once more so that it knows we added a new timer unit file:
    
    ```bash
    sudo systemctl daemon-reload
    ```
    
8. Finally, start and enable the timer with one single command:
    
    ```bash
    sudo systemctl enable --now weather-report.timer
    ```
    
9. Check the status of your timer:
    
    ```bash
    systemctl status weather-report.timer
    ```
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1713257695924/6860f5d7-0d8a-462f-ada0-b2c2388bd025.png align="center")
    

## References:

1. [Automate Your Tasks with systemd Timers: A Step-by-Step Guide](https://www.youtube.com/watch?v=n6BuUgkZ5T0)
    
2. [How to use systemd timers (cronjob alternative)](https://silentlad.com/how-to-use-systemd-timers-(cronjob-alternative))
    
3. [Understanding Systemd Services](https://karlygash-yakiyayeva.dev/understanding-systemd-services)
    
4. [systemd.time format](https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html)
    
5. [Systemd timers onCalendar (cron) format explained](https://silentlad.com/systemd-timers-oncalendar-(cron)-format-explained)
