Introduction
For decades, cron has been the go-to solution for scheduling tasks in Linux systems. However, systemd timers offer a modern, more integrated alternative with several advantages. In this guide, we’ll explore how to migrate from crontab to systemd timers, including the benefits, drawbacks, and practical examples.
What are Systemd Timers?
Systemd timers are unit files that control when systemd services should be executed. Unlike cron, which is a standalone daemon, systemd timers are fully integrated into the systemd ecosystem, providing better logging, dependency management, and system integration.
Advantages of Systemd Timers
1. Better Logging and Monitoring
- All timer activities are logged through journald
- Easy to view logs with `journalctl -u se…
Introduction
For decades, cron has been the go-to solution for scheduling tasks in Linux systems. However, systemd timers offer a modern, more integrated alternative with several advantages. In this guide, we’ll explore how to migrate from crontab to systemd timers, including the benefits, drawbacks, and practical examples.
What are Systemd Timers?
Systemd timers are unit files that control when systemd services should be executed. Unlike cron, which is a standalone daemon, systemd timers are fully integrated into the systemd ecosystem, providing better logging, dependency management, and system integration.
Advantages of Systemd Timers
1. Better Logging and Monitoring
- All timer activities are logged through journald
- Easy to view logs with
journalctl -u service-name - Integrated with systemd’s status reporting
2. Dependency Management
- Can specify dependencies on other services or system states
- Start services only when certain conditions are met
- Better control over execution order
3. Flexible Scheduling
- Calendar-based scheduling (similar to cron)
- Monotonic timers (relative to boot time, startup, etc.)
- Can trigger services on system events
4. Resource Control
- Integration with cgroups for resource limiting
- CPU and memory limits can be set per service
- Better process isolation
5. Failure Handling
- Automatic restart policies
- Notification on failure
- Better error tracking
Disadvantages of Systemd Timers
1. Complexity
- Requires two files (.service and .timer) instead of one line
- Steeper learning curve compared to cron
- More verbose configuration
2. Portability
- Only works on systemd-based systems
- Cron is more universal across Unix-like systems
3. User-Level Timers
- User timers require
--userflag and lingering enabled - Slightly more complex setup for non-root users
Basic Setup: Creating Your First Systemd Timer
Step 1: Create the Service File
First, create a service file that defines what should be executed. Save this as /etc/systemd/system/backup-script.service:
[Unit]
Description=Daily Backup Script
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
User=backup
Group=backup
ExecStart=/usr/local/bin/backup.sh
StandardOutput=journal
StandardError=journal
# Resource limits
CPUQuota=50%
MemoryLimit=1G
Step 2: Create the Timer File
Next, create the corresponding timer file. Save this as /etc/systemd/system/backup-script.timer:
[Unit]
Description=Run backup script daily at 2 AM
Requires=backup-script.service
[Timer]
OnCalendar=daily
OnCalendar=*-*-* 02:00:00
Persistent=true
Unit=backup-script.service
[Install]
WantedBy=timers.target
Step 3: Enable and Start the Timer
# Reload systemd to recognize new files
sudo systemctl daemon-reload
# Enable the timer to start on boot
sudo systemctl enable backup-script.timer
# Start the timer immediately
sudo systemctl start backup-script.timer
# Check timer status
sudo systemctl status backup-script.timer
# List all active timers
sudo systemctl list-timers --all
Common Timer Configurations
Every Hour
[Timer]
OnCalendar=hourly
# Or more explicitly:
OnCalendar=*-*-* *:00:00
Every 15 Minutes
[Timer]
OnCalendar=*:0/15
Weekdays at 9 AM
[Timer]
OnCalendar=Mon-Fri *-*-* 09:00:00
Every Monday at 3 AM
[Timer]
OnCalendar=Mon *-*-* 03:00:00
5 Minutes After Boot
[Timer]
OnBootSec=5min
Combination: Daily and After Boot
[Timer]
OnCalendar=daily
OnBootSec=10min
Persistent=true
Migration Example: From Crontab to Systemd Timer
Original Crontab Entry
0 2 * * * /usr/local/bin/cleanup.sh
Equivalent Systemd Configuration
cleanup.service:
[Unit]
Description=Cleanup temporary files
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cleanup.sh
cleanup.timer:
[Unit]
Description=Daily cleanup at 2 AM
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Understanding Key Timer Options
OnCalendar
Defines when the timer should trigger based on calendar time. Syntax is flexible:
daily=*-*-* 00:00:00weekly=Mon *-*-* 00:00:00monthly=*-*-01 00:00:00yearly=*-01-01 00:00:00
Persistent
When set to true, if the system was off when the timer should have triggered, it will run immediately upon next boot.
OnBootSec / OnStartupSec
Triggers the timer relative to system boot or systemd startup.
OnUnitActiveSec / OnUnitInactiveSec
Triggers relative to when the service was last active or inactive.
AccuracySec
Defines the accuracy window for timer triggers (default: 1 minute). Can be adjusted for power saving:
AccuracySec=1h
Useful Management Commands
# View all timers and their next trigger times
systemctl list-timers
# Check specific timer status
systemctl status backup-script.timer
# View service logs
journalctl -u backup-script.service
# View logs since last boot
journalctl -u backup-script.service -b
# Follow logs in real-time
journalctl -u backup-script.service -f
# Manually trigger a timer's service
systemctl start backup-script.service
# Stop a timer
systemctl stop backup-script.timer
# Disable a timer from starting on boot
systemctl disable backup-script.timer
# Check when timer will next trigger
systemctl list-timers backup-script.timer
User-Level Timers
For non-root users, timers can be placed in ~/.config/systemd/user/ and managed with the --user flag:
# Enable user timer
systemctl --user enable my-script.timer
# Start user timer
systemctl --user start my-script.timer
# List user timers
systemctl --user list-timers
# Enable lingering (allows user timers to run without login)
sudo loginctl enable-linger username
Advanced Example: Service with Email Notification
backup-with-notification.service:
[Unit]
Description=Backup with notification
OnFailure=failure-notification@%n.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
ExecStartPost=/usr/local/bin/notify-success.sh
Debugging Tips
Check syntax: Use systemd-analyze calendar "Mon *-*-* 09:00:00" to verify OnCalendar expressions
1.
Dry run: Test your service manually before enabling the timer:
sudo systemctl start backup-script.service
- Verbose logging: Add to service file:
[Service]
StandardOutput=journal
StandardError=journal
- Check timer accuracy:
systemctl show backup-script.timer -p NextElapseUSecRealtime
Conclusion
Systemd timers provide a powerful, modern alternative to cron with better integration, logging, and flexibility. While they require more initial setup, the benefits in maintainability, monitoring, and system integration make them worth considering for new deployments.
For existing systems with working cron jobs, migration can be gradual. Start with new scheduled tasks using systemd timers, and migrate critical cron jobs over time as you become more comfortable with the syntax and tooling.
Quick Decision Guide:
Use Systemd Timers when:
- You need detailed logging and monitoring
- Dependencies on other services are required
- Resource limiting is important
- You’re on a systemd-based distribution
Stick with Cron when:
- Simplicity is paramount
- Portability across systems is required
- You have legacy scripts that work well
- System doesn’t use systemd
Have you migrated from cron to systemd timers? Share your experiences in the comments below!