How to Schedule Tasks with crontab and systemd timers
Learn how to schedule recurring tasks on Linux using crontab and systemd timers. Step-by-step guidance, examples, and tips for DevOps and Linux beginners.
Short introduction (2–3 sentences)
Scheduling recurring tasks is essential for backups, maintenance, and automation. This guide walks you through two common Linux scheduling tools—crontab and systemd timers—showing how to create, test, and troubleshoot jobs in a practical, beginner-friendly way.
crontab: quick overview and syntax
crontab (cron) is a time-based job scheduler available on most Unix-like systems. Each user can have a crontab file that defines commands to run at specific times. The basic crontab line has five time fields followed by the command:
- minute (0-59)
- hour (0-23)
- day of month (1-31)
- month (1-12)
- day of week (0-7, where both 0 and 7 mean Sunday)
Example: edit your crontab and schedule a daily job at 2:30 AM.
# Edit your crontab
$ crontab -e
# Add a job (example)
30 2 * * * /usr/local/bin/daily-maintenance.sh >> /var/log/daily-maint.log 2>&1
Notes:
- Use full paths to executables and scripts.
- Redirect stdout/stderr to files for troubleshooting.
- The environment is minimal—set PATH or source profile files if needed.
If you want a shorthand for common intervals, cron supports strings like @daily, @hourly, @reboot:
# Run at boot
@reboot /usr/local/bin/start-on-boot.sh
# Run daily
@daily /usr/local/bin/daily-job.sh
Practical crontab examples
Here are common patterns and how to make them robust.
- Run a script and ensure PATH and environment:
# crontab -e
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * /home/user/scripts/backup.sh >> /home/user/logs/backup.log 2>&1
- Example backup script (keep it executable):
#!/bin/bash
# /home/user/scripts/backup.sh
set -euo pipefail
tar -czf /home/user/backups/home-$(date +%F).tar.gz /home/user/data
Make executable:
$ chmod +x /home/user/scripts/backup.sh
- Testing cron jobs:
- Use a short interval like every minute to test.
```- /home/user/scripts/test-cron.sh >> /home/user/logs/test.log 2>&1
```
- /home/user/scripts/test-cron.sh >> /home/user/logs/test.log 2>&1
- Inspect mail for cron output (some systems deliver stderr/stdout to local mail).
Check cron logs (system-specific):
```
On many systems
$ sudo grep CRON /var/log/syslog
On systemd-journald systems
$ sudo journalctl -u cron.service
## systemd timers: overview and creating timers
systemd timers pair a .timer unit with a .service unit. Timers offer more precise calendaring (OnCalendar), better logging via journalctl, and dependency management with systemd.
Create a simple service and timer that runs a script daily at 02:00.
1) Service unit: /etc/systemd/system/daily-backup.service
[Unit]
Description=Daily backup job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
2) Timer unit: /etc/systemd/system/daily-backup.timer
[Unit]
Description=Daily backup timer
[Timer]
OnCalendar=--* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Enable and start the timer:
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now daily-backup.timer
$ sudo systemctl list-timers --all | grep daily-backup
Check status and logs:
$ sudo systemctl status daily-backup.timer
$ sudo systemctl status daily-backup.service
$ sudo journalctl -u daily-backup.service --since "1 hour ago"
Key advantages of systemd timers:
- OnCalendar supports calendar events (e.g., "Mon *-*-* 03:00:00" or "weekly").
- Persistent=true runs missed jobs if the system was down.
- Better integration with systemd targets and service dependencies.
## When to use crontab vs systemd timers
Both tools can schedule tasks, but they have different strengths.
Checklist and examples:
Quick checks
Display your crontab
$ crontab -l
Show timers
$ systemctl list-timers --all
See logs for systemd timer/service
$ sudo journalctl -u mytask.service
Check cron log (if available)
$ sudo grep CRON /var/log/syslog
When to choose crontab:
- You're on a minimal system without systemd.
- You want user-specific jobs that don't need system-level integration.
- You prefer the simplicity of crontab's minute/hour/day fields.
When to choose systemd timers:
- You want better logging (journalctl) and unit dependencies.
- You need features like Persistent, OnBootSec, randomized delays (RandomizedDelaySec), or OnCalendar’s flexible syntax.
- Your environment already uses systemd for service management.
Example decision:
- Run a user-specific, low-risk script → crontab (use systemd user timers if you want journal integration).
- Run system maintenance, require restart resilience, or want to tie into system targets → systemd timers.
## Common Pitfalls
- Environment and PATH issues:
- Cron and systemd services run with a limited environment. Always use full paths or export PATH at the top of scripts.
- Example fix:
```
# In script
export PATH=/usr/local/bin:/usr/bin:/bin
```
- Forgetting to make scripts executable or using the wrong interpreter:
- Ensure shebang and permissions are correct:
```
$ chmod +x /usr/local/bin/myscript.sh
#!/bin/bash
```
- Not checking logs:
- Cron output may be emailed or logged; systemd jobs go to journalctl. Always check logs if a job doesn't run as expected:
```
$ sudo journalctl -u myjob.service
$ sudo grep CRON /var/log/syslog
```
## Next Steps
- Try a simple timer: create a small service + timer that appends a timestamp to a file, enable it, and inspect journalctl.
$ echo '#!/bin/sh' > /usr/local/bin/timer-test.sh
$ echo 'date >> /tmp/timer-test.log' >> /usr/local/bin/timer-test.sh
$ chmod +x /usr/local/bin/timer-test.sh
create units and enable the timer as shown earlier
- Learn systemd timer expressions: read man systemd.timer and experiment with OnCalendar values for weekly, monthly, and complex schedules.
$ man systemd.timer
```
- Harden and monitor production jobs: add logging, exit codes, and alerts (use mail, Prometheus exporters, or a simple health-check script) to ensure tasks run reliably.
👉 Explore more IT books and guides at dargslan.com.