DEV Community

kingyou
kingyou

Posted on

Replacing Crontab with Systemd Timer: Benefits, Examples, and Migration Guide

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 --user flag 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Common Timer Configurations

Every Hour

[Timer]
OnCalendar=hourly
# Or more explicitly:
OnCalendar=*-*-* *:00:00
Enter fullscreen mode Exit fullscreen mode

Every 15 Minutes

[Timer]
OnCalendar=*:0/15
Enter fullscreen mode Exit fullscreen mode

Weekdays at 9 AM

[Timer]
OnCalendar=Mon-Fri *-*-* 09:00:00
Enter fullscreen mode Exit fullscreen mode

Every Monday at 3 AM

[Timer]
OnCalendar=Mon *-*-* 03:00:00
Enter fullscreen mode Exit fullscreen mode

5 Minutes After Boot

[Timer]
OnBootSec=5min
Enter fullscreen mode Exit fullscreen mode

Combination: Daily and After Boot

[Timer]
OnCalendar=daily
OnBootSec=10min
Persistent=true
Enter fullscreen mode Exit fullscreen mode

Migration Example: From Crontab to Systemd Timer

Original Crontab Entry

0 2 * * * /usr/local/bin/cleanup.sh
Enter fullscreen mode Exit fullscreen mode

Equivalent Systemd Configuration

cleanup.service:

[Unit]
Description=Cleanup temporary files

[Service]
Type=oneshot
ExecStart=/usr/local/bin/cleanup.sh
Enter fullscreen mode Exit fullscreen mode

cleanup.timer:

[Unit]
Description=Daily cleanup at 2 AM

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target
Enter fullscreen mode Exit fullscreen mode

Understanding Key Timer Options

OnCalendar

Defines when the timer should trigger based on calendar time. Syntax is flexible:

  • daily = *-*-* 00:00:00
  • weekly = Mon *-*-* 00:00:00
  • monthly = *-*-01 00:00:00
  • yearly = *-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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Debugging Tips

  1. Check syntax: Use systemd-analyze calendar "Mon *-*-* 09:00:00" to verify OnCalendar expressions

  2. Dry run: Test your service manually before enabling the timer:

   sudo systemctl start backup-script.service
Enter fullscreen mode Exit fullscreen mode
  1. Verbose logging: Add to service file:
   [Service]
   StandardOutput=journal
   StandardError=journal
Enter fullscreen mode Exit fullscreen mode
  1. Check timer accuracy:
   systemctl show backup-script.timer -p NextElapseUSecRealtime
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)