Introduction / Why This Is Needed
Systemd timers are a modern job scheduling mechanism in systems using systemd (virtually all current Linux distributions). They replace the classic cron, offering tighter integration with the init system, advanced scheduling capabilities, and a unified event log (journalctl). With timers, you can automate backups, log cleanup, update checks, or run any script on a schedule, with a delay after boot, or even in response to other system events.
After completing this guide, you will be able to create reliable and easily manageable jobs that correctly handle missed runs (e.g., if the computer was off) and provide detailed information about their operations.
Requirements / Preparation
- System with systemd: Ensure your distribution uses systemd (check
echo $INIT_SYSTEMorps -p 1 -o comm=). - Superuser (root) privileges: Creating system units in
/etc/systemd/system/and managing them requires administrator rights. For user-specific timers (without sudo), use~/.config/systemd/user/. - Basic understanding of systemd: It is helpful to know what unit files are and the
systemctlcommand. - Text editor: For example,
nano,vim, orvi.
Step 1: Create the Service File (.service)
A timer does not execute commands directly. It activates a service file (.service), which contains the instructions for running your task. Let's start with that.
We'll create a simple service to back up the home directory. Save this config as /etc/systemd/system/home-backup.service:
[Unit]
Description=Home directory backup
# Run the service only if the network is available (optional)
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
# The command to execute. Example using tar with compression.
ExecStart=/bin/tar -czf /var/backups/home_$(date +\%Y-\%m-\%d).tar.gz /home
# Indicates the job runs once per timer activation
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Key points:
Type=oneshot: The service process terminates afterExecStartcompletes. Used for one-off tasks.ExecStart: The main command. Note the escaping of%indate(requires\%).RemainAfterExit=yes: Allows the service to be considered active after the command finishes. Useful for status monitoring.- To run multiple commands, use a script and point
ExecStartto it, or useExecStartPre/ExecStartPost.
Step 2: Create the Timer File (.timer)
Now create the timer file that will trigger our service on a schedule. Save it as /etc/systemd/system/home-backup.timer:
[Unit]
Description=Timer for daily home directory backup
[Timer]
# Schedule: every day at 02:30
OnCalendar=*-*-* 02:30:00
# If the job was missed (computer was off), run it on the next boot
Persistent=true
# The service to activate
Unit=home-backup.service
[Install]
WantedBy=timers.target
Key points:
OnCalendar=*-*-* 02:30:00: Flexible calendar syntax.*means "any value." Here: any year, any month, any day at 02:30.- Examples:
Mon *-*-* 09:00:00(every Monday at 9 AM),*-*-1 00:00:00(the first day of every month).
- Examples:
Persistent=true: A critically important option! If the computer is off at the scheduled time,systemdwill run the job immediately upon the next system boot.Unit=home-backup.service: Explicitly specifies which service to start. If the service filename matches the timer name (e.g.,home-backup.timerandhome-backup.service), this parameter can be omitted.
Step 3: Reload systemd Configuration
After creating both files, you must inform systemd of their existence. Run:
sudo systemctl daemon-reload
This command forces systemd to reread all configuration files. Without it, new timers and services will not be visible to the system.
Step 4: Enable and Start the Timer
Now you need to enable the timer (so it starts automatically at boot) and optionally start it immediately for testing.
# 1. Enable the timer to start automatically at boot
sudo systemctl enable home-backup.timer
# 2. Start the timer immediately (for testing)
sudo systemctl start home-backup.timer
# 3. Check the status
sudo systemctl status home-backup.timer
You should see an active (active (waiting)) timer and the next run time (Next elapse).
Step 5: Monitoring and Management
View all active timers
To see a list of all configured timers and their next activation times, use:
systemctl list-timers
This command displays a table with the timer name, next run time, last run time, and the unit it activates.
View logs
Everything your service outputs (including errors) goes into the systemd journal. Use journalctl to view it:
# Logs for the specific timer and its associated service
sudo journalctl -u home-backup.timer -u home-backup.service -f
# Logs from the last day
sudo journalctl -u home-backup.service --since "1 day ago"
Stopping and disabling
- Stop the current run (if it's in progress):
sudo systemctl stop home-backup.timer - Stop and disable autostart:
sudo systemctl disable --now home-backup.timer
Step 6: Advanced Features and Examples
Run with a delay after boot
If a task should run not on a calendar schedule, but after a certain time post-boot (e.g., to allow network services to start), use OnBootSec:
[Timer]
OnBootSec=15min
Unit=home-backup.service
This runs the service 15 minutes after boot. You can combine: OnBootSec=5min and OnUnitActiveSec=1h to run after 5 minutes post-boot and then every hour.
Periodic run (interval)
For intervals not tied to a calendar (e.g., "every 30 minutes"), use OnUnitActiveSec:
[Timer]
OnUnitActiveSec=30min
Unit=home-backup.service
This means: run the service every 30 minutes after its last successful run.
Randomized (staggered) execution
To avoid a "thundering herd" when many timers fire simultaneously on multiple machines (e.g., for updates), add RandomizedDelaySec:
[Timer]
OnCalendar=daily
RandomizedDelaySec=1h
The job will run at a random moment within one hour after midnight.
Verifying the Result
- Ensure the timer is active:
systemctl is-active home-backup.timershould returnactive. - Check the schedule:
systemctl list-timers | grep home-backupwill show the next run time. - Wait for activation (or manually trigger it with
sudo systemctl start home-backup.timer) and check:- The backup file:
ls -lh /var/backups/ - Service status:
systemctl status home-backup.service - Journal:
sudo journalctl -u home-backup.service --no-pager -n 20
- The backup file:
If the backup was created and there are no errors in the logs—everything is working.
Common Issues
Timer doesn't run on schedule
- Check
OnCalendarsyntax. Usesystemd-analyze calendar '*-*-* 02:30:00'to validate. - Ensure
Persistent=trueis set if the computer might be off at the scheduled time. - Check for conflicts with
cron. Systemd andcronare independent. If the job already exists incron, disable it to avoid duplicate runs.
Service started by timer exits with an error
- Check the service logs with
journalctl -u <service>.service. The error is almost always in theExecStartcommand (wrong path, missing permissions, insufficient space). - Verify access permissions to the script/command and target directories/files. System services often require
root. - Confirm
Type=oneshotmatches your task. If the command starts a daemon, you may needType=forkingorType=notify.
Timer not visible in systemctl list-timers
- Did you run
daemon-reloadafter creating the files? - Are the files named and located correctly? For system units:
/etc/systemd/system/<name>.timer. For user units:~/.config/systemd/user/. - Is the timer enabled?
sudo systemctl enable <name>.timer(for system) orsystemctl --user enable <name>.timer(for user). - Check if the timer is already active:
systemctl status <name>.timer. If it showsactive (waiting), it's working. Ifinactive (dead), it may need to be started (start).