Table of Contents
- Introduction to Systemd Timers
- How Systemd Timers Work (vs. Cron)
- Components of a Systemd Timer
- Creating Your First Timer: A Step-by-Step Guide
- Advanced Timer Configuration
- Managing Timers: Commands and Best Practices
- Debugging and Troubleshooting Timers
- Real-World Use Cases
- Conclusion
- References
Introduction to Systemd Timers
Systemd timers are part of the systemd suite, designed to trigger systemd service units at specific times or intervals. Unlike cron, which uses a simple text-based crontab file, timers are defined as systemd units (.timer files) that work in tandem with service units (.service files). The timer unit acts as a scheduler, while the service unit contains the actual task to execute.
Key Advantages Over Cron:
- Tight Integration with Systemd: Timers can depend on other systemd units (e.g.,
network-online.targetfor internet-dependent tasks) and leverage systemd features like cgroups, logging, and resource management. - Flexible Scheduling: Supports both calendar-based events (e.g., “every 1st of the month”) and monotonic (relative) time (e.g., “30 seconds after boot”).
- Enhanced Logging: All timer and task output is captured by
journald, making debugging easier withjournalctl. - Missed Task Handling: The
Persistentdirective ensures tasks run even if the system was offline during the scheduled time. - Randomized Delays: Prevent “thundering herd” problems with
RandomizedDelaySecto spread out task execution.
How Systemd Timers Work (vs. Cron)
To understand systemd timers, it helps to contrast them with cron:
| Feature | Cron | Systemd Timers |
|---|---|---|
| Configuration | Text-based crontab files (/etc/crontab, crontab -e). | Systemd unit files (.timer and .service). |
| Scheduling | Calendar-based only (e.g., 0 3 * * * for 3 AM daily). | Both calendar-based (OnCalendar) and monotonic (relative) time (OnBootSec, OnActiveSec). |
| Dependencies | None; tasks run independently. | Can depend on systemd targets/services (e.g., After=network.target). |
| Logging | Limited; output sent to email or /var/log/cron. | Integrated with journald; logs accessible via journalctl. |
| Missed Tasks | Ignored by default (unless using anacron for daily/weekly tasks). | Persistent=true ensures missed tasks run on next boot. |
Systemd timers bridge the gap between simple cron jobs and complex systemd service dependencies, making them ideal for modern Linux environments.
Components of a Systemd Timer
A systemd timer setup requires two files:
- A timer unit file (
.timer): Defines when the task should run. - A service unit file (
.service): Defines what task to run (the actual command/script).
1. The Timer Unit File (.timer)
The timer unit file (e.g., backup.timer) contains scheduling logic. It uses three main sections: [Unit], [Timer], and [Install].
Example Timer File Structure:
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup of user documents
Documentation=man:backup(1)
[Timer]
# Calendar event: Run daily at 3 AM
OnCalendar=*-*-* 03:00:00
# Wait 5 minutes after boot before first run (if missed)
OnBootSec=5min
# Add a random 1-5 minute delay to avoid server load spikes
RandomizedDelaySec=1min 5min
# Ensure missed tasks run on next boot
Persistent=true
# Accuracy: Allow 1 minute deviation from scheduled time (default: 1min)
AccuracySec=1min
[Install]
# Enable timer on boot by linking to multi-user.target
WantedBy=multi-user.target
Key [Timer] Directives:
OnCalendar: Calendar-based schedule (syntax below).OnBootSec: Run task X seconds/minutes/hours after boot (e.g.,OnBootSec=10min).OnActiveSec: Run task X seconds after the timer itself is activated (e.g.,OnActiveSec=1h).RandomizedDelaySec: Add a random delay (e.g.,RandomizedDelaySec=30sto5min).Persistent: Iftrue, run missed tasks on next boot (default:false).AccuracySec: Tolerance for schedule deviation (reduces CPU wake-ups; default:1min).
2. The Service Unit File (.service)
The service unit file (e.g., backup.service) defines the task to execute when the timer triggers. It uses the [Unit], [Service], and [Install] sections (though [Install] is often optional for timer-driven services).
Example Service File:
# /etc/systemd/system/backup.service
[Unit]
Description=Backup user documents to /backup
Requires=mount-backup-drive.service # Depend on backup drive being mounted
After=mount-backup-drive.service
[Service]
# Run as non-root user (safer than root)
User=john
Group=john
# Command to execute: Backup /home/john/docs to /backup/docs-YYYY-MM-DD
ExecStart=/bin/bash -c 'cp -r /home/john/docs /backup/docs-$(date +\%Y-\%m-\%d)'
# Ensure the task runs to completion even if the user logs out
Type=oneshot
Key [Service] Directives:
ExecStart: The command/script to run (required).User/Group: Run the task as a specific user/group (avoidrootunless necessary).Type=oneshot: For tasks that run once and exit (default for timers).Requires/After: Dependencies (e.g., ensure a backup drive is mounted first).
Creating Your First Timer: Step-by-Step
Let’s walk through creating a daily backup timer to automate backing up a user’s Documents folder to /backup.
Step 1: Create the Service File
First, define the backup task in a .service file. We’ll use backup.service:
sudo nano /etc/systemd/system/backup.service
Add the following content:
[Unit]
Description=Daily backup of Documents folder
Documentation=https://example.com/backup-guide
[Service]
User=john # Replace with your username
Group=john
Type=oneshot
# Backup command: Copy Documents to /backup with a timestamp
ExecStart=/bin/bash -c 'rsync -av /home/john/Documents /backup/Documents-$(date +\%Y\%m\%d)'
- We use
rsync -avinstead ofcpfor incremental backups (faster for large folders). - The timestamp
$(date +\%Y\%m\%d)ensures unique backup folders (e.g.,Documents-20240520).
Step 2: Create the Timer File
Next, create the .timer file to schedule the backup. Use backup.timer:
sudo nano /etc/systemd/system/backup.timer
Add:
[Unit]
Description=Trigger daily backup of Documents
Requires=backup.service # Ensure the service exists
[Timer]
# Run daily at 2:30 AM
OnCalendar=*-*-* 02:30:00
# Add a random 1-5 minute delay to avoid server load
RandomizedDelaySec=1min 5min
# If the system is off at 2:30 AM, run backup on next boot
Persistent=true
[Install]
WantedBy=multi-user.target # Enable timer on boot
Step 3: Enable and Start the Timer
To activate the timer:
-
Reload systemd to detect the new units:
sudo systemctl daemon-reload -
Enable the timer to run on boot:
sudo systemctl enable backup.timer -
Start the timer immediately (no need to wait for boot):
sudo systemctl start backup.timer
Step 4: Verify the Timer
Check if the timer is active and scheduled:
sudo systemctl list-timers --all backup.timer
Output should look like:
NEXT LEFT LAST PASSED UNIT ACTIVATES
Tue 2024-05-21 02:30:00 UTC 11h left n/a n/a backup.timer backup.service
To view logs later (after the first run):
journalctl -u backup.service # Logs from the backup task
journalctl -u backup.timer # Logs from the timer itself
Advanced Timer Configuration
Systemd timers support sophisticated scheduling scenarios. Let’s explore key advanced features.
1. Calendar Events (OnCalendar)
The OnCalendar directive uses a flexible syntax to define calendar-based schedules. The format is:
OnCalendar=<year>-<month>-<day> <hour>:<minute>:<second>
Wildcards (*), ranges (-), and steps (/) are supported. Examples:
| Schedule | OnCalendar Syntax |
|---|---|
| Daily at 3:15 AM | *-*-* 03:15:00 |
| Every Monday at 9 PM | Mon *-*-* 21:00:00 |
| 1st of every month at noon | *-*-01 12:00:00 |
| Every 15 minutes | *:0/15 (shorthand for *-*-* *:0/15:00) |
| Weekdays (Mon-Fri) at 8 AM | Mon,Tue,Wed,Thu,Fri *-*-* 08:00:00 |
Shorthand aliases like daily, weekly, or monthly also work (e.g., OnCalendar=daily = *-*-* 00:00:00).
2. Monotonic (Relative) Timers
Monotonic timers schedule tasks relative to system events (e.g., boot time or timer activation), not calendar time. Use these directives:
OnBootSec: Run X seconds after the system boots (e.g.,OnBootSec=5min).OnActiveSec: Run X seconds after the timer is activated (e.g.,OnActiveSec=1h).OnUnitActiveSec: Run X seconds after the service last ran (e.g.,OnUnitActiveSec=6hfor every 6 hours after the service finishes).
Example: Run a cleanup task 10 minutes after boot and every 2 hours thereafter:
[Timer]
OnBootSec=10min # First run: 10min after boot
OnUnitActiveSec=2h # Subsequent runs: 2h after the service last finished
3. Randomized Delays
To prevent multiple timers from running simultaneously (e.g., after a reboot), use RandomizedDelaySec to add a random delay. Syntax:
RandomizedDelaySec=30s # Fixed 30-second delay
RandomizedDelaySec=1min 5min # Random delay between 1-5 minutes
4. Persistent Tasks
If the system is offline during a scheduled run, Persistent=true ensures the task runs on the next boot. Example:
[Timer]
OnCalendar=*-*-* 01:00:00 # Daily at 1 AM
Persistent=true # Run 1 AM backup on next boot if system was off
Managing Timers: Commands and Best Practices
Systemd provides a suite of commands to manage timers. Here are the most useful:
List All Active Timers
View upcoming and recent timer runs:
systemctl list-timers
Add --all to include inactive timers:
systemctl list-timers --all
Check Timer Status
View details about a specific timer (e.g., backup.timer):
systemctl status backup.timer
Output includes next run time, last run time, and active status.
Start/Stop/Enable/Disable Timers
-
Start a timer immediately:
sudo systemctl start backup.timer -
Stop a running timer (prevents future runs until restarted):
sudo systemctl stop backup.timer -
Enable a timer to run on boot:
sudo systemctl enable backup.timer -
Disable a timer (stops it from running on boot):
sudo systemctl disable backup.timer
View Timer/Service Logs
Use journalctl to debug timers and tasks:
-
Logs for the timer itself:
journalctl -u backup.timer -
Logs for the associated service (task output):
journalctl -u backup.service -
Follow real-time logs:
journalctl -u backup.service -f
Debugging and Troubleshooting Timers
If your timer isn’t working, use these steps to diagnose issues:
1. Verify Timer and Service Files
Ensure the timer and service files are valid:
# Check for syntax errors in the timer
sudo systemctl cat backup.timer # View the timer file
sudo systemd-analyze verify backup.timer # Validate syntax
# Check the service file similarly
sudo systemctl cat backup.service
sudo systemd-analyze verify backup.service
2. Check if the Timer Is Enabled/Active
systemctl is-enabled backup.timer # Should return "enabled"
systemctl is-active backup.timer # Should return "active"
3. Inspect Logs for Errors
Use journalctl to check for failed runs or service errors:
journalctl -u backup.service --since "24 hours ago" # Last 24 hours of service logs
Common issues:
ExecStartcommand errors (e.g., missing script, permission denied).- Dependencies not met (e.g.,
Requires=mount-backup-drive.servicefailed).
4. Test the Service Manually
Bypass the timer and run the service directly to validate the task:
sudo systemctl start backup.service # Run the service now
systemctl status backup.service # Check if it succeeded
Real-World Use Cases
Systemd timers shine in scenarios where flexibility and system integration matter. Here are common use cases:
1. Scheduled Backups with Dependencies
Use Requires=network.target and After=network.target to ensure backups run only when the internet is available (e.g., cloud backups).
2. Post-Boot Maintenance
Run tasks like disk checks or software updates 10 minutes after boot with OnBootSec=10min.
3. Periodic Log Rotation
Replace logrotate (which uses cron) with a timer to rotate logs hourly, with OnCalendar=*:00 and RandomizedDelaySec=5min.
4. Syncing Data with a Remote Server
Use OnUnitActiveSec=30min to sync files every 30 minutes after the last sync, ensuring minimal bandwidth usage.
5. Missed Task Recovery
For critical tasks like security scans, Persistent=true ensures scans run even if the system was offline during the scheduled time.
Conclusion
Systemd timers offer a modern, flexible alternative to cron for automating tasks in Linux. By combining calendar-based and relative scheduling with systemd’s dependency management and logging, they simplify complex automation workflows. Whether you’re a home user automating backups or a sysadmin managing enterprise servers, systemd timers provide the tools to keep your systems running efficiently.
Start small (e.g., the daily backup example in this blog) and gradually explore advanced features like dependencies and persistent tasks. With systemd timers, you’ll gain greater control over your system’s automation than ever before.