systemd Timer vs Restart Directive: Best Practices for Periodic Script Execution


4 views

When managing periodic script execution on Linux systems with systemd, administrators face a fundamental choice between using timer units or service unit restart directives. Both approaches can achieve similar timing patterns, but with important technical and operational differences.

Systemd timers provide the most robust solution for periodic execution. They offer:

  • Precise scheduling capabilities with calendar semantics
  • Proper dependency handling between units
  • Persistent state tracking (LastTriggerUSec)
  • Flexible failure handling through OnFailure dependencies
# Example timer unit (example.timer)
[Unit]
Description=Run example every 5 minutes

[Timer]
OnCalendar=*:0/5
AccuracySec=1min
Persistent=true

[Install]
WantedBy=timers.target

Using Restart=always with RestartSec provides a simpler but more limited approach:

  • No external timer unit required
  • Immediate restart capability (no wait for next schedule)
  • Simplicity for always-running services
# Example service unit with restart (example.service)
[Unit]
Description=Example periodic service

[Service]
Type=simple
ExecStart=/usr/local/bin/example-script
Restart=always
RestartSec=300

[Install]
WantedBy=multi-user.target
Factor Timer Restart
Scheduling Precision High (nanosecond) Low (second)
Execution Guarantee Calendar-based Process-based
Failure Handling Separate unit Built-in
Logging Separate entries Continuous
Resource Usage Lower Higher

For frequent executions (e.g., every minute), timers show significant advantages:

  • Lower CPU overhead (no constant process monitoring)
  • No accumulation of zombie processes
  • Better integration with systemd's job management

For most periodic script scenarios, systemd timers represent the superior solution because:

  1. They properly model the scheduling intent
  2. They integrate better with systemd's ecosystem
  3. They provide more monitoring capabilities through systemctl

The restart approach should be reserved for:

  • Services that must remain running continuously
  • Quick recovery scenarios where process restart is preferred
  • Legacy compatibility requirements

Converting from cron to systemd timers:

# Original cron entry
*/5 * * * * /usr/local/bin/backup-script

# Equivalent timer unit
[Unit]
Description=Backup timer

[Timer]
OnCalendar=*-*-* *:0/5:00
Unit=backup.service

[Install]
WantedBy=timers.target

When automating periodic tasks in Linux, developers often face the choice between:

  • Traditional cron jobs
  • Systemd service units with Restart directives
  • Systemd timer units

For a script needing periodic execution (e.g., every 5 minutes), here's how each approach differs:

1. Systemd Service with Restart


[Unit]
Description=My Periodic Script

[Service]
ExecStart=/usr/local/bin/myscript.sh
Restart=always
RestartSec=300

2. Systemd Timer Unit


[Unit]
Description=Run myscript every 5 minutes

[Timer]
OnUnitActiveSec=5m
OnBootSec=5m

[Install]
WantedBy=timers.target

Execution Timing Behavior

The Restart approach will:

  • Run immediately when service starts
  • Wait exactly RestartSec after previous run completes
  • Continue regardless of exit status

The Timer approach will:

  • Run at fixed intervals from service activation
  • Allow more sophisticated scheduling (calendar-based, etc.)
  • Can be configured to trigger only on successful exits

Implementation Recommendations

For most periodic scripts, timers are preferable because:

  1. They provide better visibility (systemctl list-timers)
  2. Allow more flexible scheduling options
  3. Enable proper dependency handling
  4. Support calendar-based scheduling when needed

Converting a cron job (e.g., */5 * * * * /path/to/script) to systemd:


# /etc/systemd/system/myscript.service
[Unit]
Description=My Custom Script

[Service]
Type=oneshot
ExecStart=/path/to/script

# /etc/systemd/system/myscript.timer
[Unit]
Description=Run myscript every 5 minutes

[Timer]
OnCalendar=*:0/5
AccuracySec=1m

[Install]
WantedBy=timers.target

For high-frequency tasks (e.g., every minute):

  • Timers have slightly less overhead than Restart
  • Both approaches avoid cron's forking overhead
  • Systemd provides better logging integration

For timer units:

systemctl list-timers --all
journalctl -u myscript.timer -u myscript.service
systemd-analyze verify myscript.*

For restart services:

journalctl -u myscript.service -f
systemctl status myscript.service
systemd-analyze verify myscript.service

For new implementations, prefer systemd timers because they:

  • Provide better monitoring capabilities
  • Enable more sophisticated scheduling
  • Integrate cleanly with systemd's ecosystem
  • Maintain clearer separation between execution and scheduling

Only use Restart/RestartSec when you specifically need to:

  • Immediately restart failed services
  • Maintain exactly-timed intervals between completions
  • Handle services that might crash unexpectedly