systemd Timers
A systemd timer uses a .timer unit file to schedule jobs for periodic execution. It works in combination with a corresponding .service file — when the timer fires, the service starts automatically. Compared to traditional cron, systemd timers offer additional capabilities such as centralized log management via journalctl and support for relative schedules based on elapsed time since system boot.
Syntax
# -----------------------------------------------
# Basic structure of a .timer unit file
# -----------------------------------------------
# /etc/systemd/system/{name}.timer
[Unit]
# Timer description (shown in journalctl logs)
Description={timer description}
# Dependency: the target this timer belongs to
After=network.target
[Timer]
# -----------------------------------------------
# Calendar-based scheduling (similar to cron)
# -----------------------------------------------
# OnCalendar={calendar expression}
# → Schedules the job at an absolute time (equivalent to cron's * * * * *)
# Format: {weekday} {year}-{month}-{day} {hour}:{minute}:{second}
# Examples:
# daily → every day at 00:00:00
# weekly → every Monday at 00:00:00
# monthly → the 1st of every month at 00:00:00
# *-*-* 03:00:00 → every day at 03:00:00
# Mon *-*-* 09:00 → every Monday at 09:00:00
# -----------------------------------------------
# Relative time scheduling after boot or activation
# -----------------------------------------------
# OnBootSec={time}
# → Runs once after the specified time has elapsed since system boot
# Example: 5min → runs 5 minutes after boot
# OnUnitActiveSec={time}
# → Re-runs the service after the specified time since its last activation
# Combine with OnBootSec to achieve periodic repetition
# -----------------------------------------------
# Accuracy, jitter, and persistence settings
# -----------------------------------------------
# AccuracySec={time}
# → Specifies the allowed margin of error for timer firing (default: 1min)
# → A smaller value increases precision but reduces power-saving effectiveness
# Example: 1s → second-level precision
# RandomizedDelaySec={time}
# → Adds a random delay to the firing time
# → Useful for avoiding simultaneous execution when running the same timer
# across multiple servers
# Persistent=true
# → If the system was off when the job was scheduled to run,
# the job will be executed on the next startup
# → Use this for jobs that must not be missed, such as backups
[Install]
# Target that activates this timer (typically timers.target)
WantedBy=timers.target
Directive reference
| Directive | Description |
|---|---|
OnCalendar= | Schedules the job at an absolute time. Accepts shorthand values like daily / weekly, or explicit formats like *-*-* 03:00:00. This is the closest equivalent to cron-style time specifications. |
OnBootSec= | Runs the job once after the specified time has elapsed since system boot. Accepts units such as 5min or 30s. |
OnUnitActiveSec= | Re-runs the service after the specified time since its last activation. Combine with OnBootSec to achieve periodic repetition. |
OnStartupSec= | Runs the job after the specified time since the systemd manager started. Similar to OnBootSec, but primarily used for user-session timers. |
AccuracySec= | Specifies the allowed margin of error for timer firing. The default is 1min. Setting it to 1s gives second-level precision. Smaller values increase CPU wake-ups, so balance this against power-saving requirements. |
RandomizedDelaySec= | Adds a random delay (between 0 and the specified duration) to the firing time. Useful for preventing simultaneous load spikes when the same schedule runs across multiple servers. |
Persistent= | When set to true, any jobs that were missed while the system was off will be run on the next startup. Useful for jobs that must not be skipped, such as backups. |
Unit= | Explicitly specifies the unit name that this timer activates. If omitted, the .service file with the same name as the timer is used automatically. |
WantedBy=timers.target | Written in the [Install] section. Specifies the target where the timer is registered when enabled with systemctl enable. |
Examples
/etc/systemd/system/shinji-backup.timer
# ----------------------------------------------- # Timer to back up Shinji's home directory every night at 3:00 AM # ----------------------------------------------- [Unit] Description=Shinji home directory nightly backup timer [Timer] # Fires every day at 03:00:00 OnCalendar=*-*-* 03:00:00 # Sets the allowed firing margin to 10 seconds (stricter than the default 1 minute) AccuracySec=10s # If the system was shut down and the job could not run, # it will be executed on the next startup Persistent=true [Install] WantedBy=timers.target
/etc/systemd/system/shinji-backup.service
# -----------------------------------------------
# Service file corresponding to the timer
# (Named the same as the timer file so they are linked automatically)
# -----------------------------------------------
[Unit]
Description=Shinji home directory backup
[Service]
Type=oneshot
# Specifies the user to run the backup as
User=shinji
# Compresses /home/shinji and saves it as /backup/shinji-{date}.tar.gz
ExecStart=/bin/bash -c 'tar czf /backup/shinji-$(date +%%Y%%m%%d).tar.gz /home/shinji'
# Creates the backup destination directory if it does not exist
ExecStartPre=/bin/mkdir -p /backup
$ sudo systemctl daemon-reload $ sudo systemctl enable --now shinji-backup.timer Created symlink /etc/systemd/system/timers.target.wants/shinji-backup.timer → /etc/systemd/system/shinji-backup.timer. $ systemctl list-timers shinji-backup.timer NEXT LEFT LAST PASSED UNIT ACTIVATES Wed 2026-03-25 03:00:00 JST 18h left - - shinji-backup.timer shinji-backup.service $ journalctl -u shinji-backup.service --since today Mar 25 03:00:00 nerv-server systemd[1]: Starting Shinji home directory backup... Mar 25 03:00:02 nerv-server systemd[1]: shinji-backup.service: Succeeded. Mar 25 03:00:02 nerv-server systemd[1]: Finished Shinji home directory backup.
Run once after boot, then repeat every 10 minutes (relative time example)
# ----------------------------------------------- # /etc/systemd/system/rei-sync.timer # Rei data sync timer (first run 5 minutes after boot, then every 10 minutes) # ----------------------------------------------- [Unit] Description=Rei data sync timer [Timer] # Runs the first sync 5 minutes after system boot OnBootSec=5min # Runs the next sync 10 minutes after the previous service activation # Combined with OnBootSec, this repeats at 5 min, 15 min, 25 min, ... OnUnitActiveSec=10min # Adds a random delay of 0–30 seconds when running on multiple servers simultaneously RandomizedDelaySec=30s [Install] WantedBy=timers.target
$ sudo systemctl enable --now rei-sync.timer $ systemctl list-timers rei-sync.timer NEXT LEFT LAST PASSED UNIT ACTIVATES Wed 2026-03-25 08:52:17 JST 9min left Wed 2026-03-25 08:42:05 JST 41s ago rei-sync.timer rei-sync.service
Checking, stopping, and removing a timer
# ----------------------------------------------- # Timer management commands # ----------------------------------------------- # List all registered timers and their next scheduled run time systemctl list-timers # Show detailed status of a specific timer systemctl status shinji-backup.timer # Temporarily stop the timer (the auto-start setting is preserved) sudo systemctl stop shinji-backup.timer # Restart the timer sudo systemctl start shinji-backup.timer # Disable auto-start and stop the timer sudo systemctl disable --now shinji-backup.timer # After deleting the unit file, reload systemd configuration sudo systemctl daemon-reload
$ systemctl list-timers NEXT LEFT LAST PASSED UNIT ACTIVATES Wed 2026-03-25 09:00:00 JST 17min left Wed 2026-03-25 08:00:00 JST 43min ago logrotate.timer logrotate.service Wed 2026-03-25 09:52:00 JST 1h 9min left Wed 2026-03-25 08:48:00 JST 3min ago rei-sync.timer rei-sync.service Thu 2026-03-26 03:00:00 JST 18h left - - shinji-backup.timer shinji-backup.service 3 timers listed.
Overview
A systemd timer is a type of systemd unit file that schedules jobs by combining a .timer file with a .service file. Like crontab, it supports periodic execution, but systemd timers offer several advantages. Job execution logs can be managed centrally alongside systemd logs using journalctl -u {service-name}. Setting Persistent=true ensures that any jobs missed while the system was off are caught up on the next startup. Additional fine-grained controls unavailable in cron include distributed execution via RandomizedDelaySec and precision tuning via AccuracySec. On the other hand, cron is available by default in most environments and has a simpler configuration, making it a viable choice for straightforward scheduling tasks. For systems you are building from scratch or environments already managed around systemd, timers are worth considering.
If you find any errors or copyright issues, please contact us.