Using Cron and Systemd Timers for Scheduled Tasks
Linux administrators often need to run commands automatically: rotate logs, create backups, renew certificates, check disk usage, or refresh application data. On RHEL, CentOS, Fedora, and related distributions, cron and systemd timers provide dependable ways to execute these jobs without manual intervention.
Cron remains widely understood and is available on almost every Unix-like system. Systemd timers offer tighter integration with service units, journal logging, dependency handling, and resource controls. Selecting the right scheduler depends on the complexity and operational importance of the task.
Australian servers also require careful time-zone planning. Sydney and Melbourne switch between AEST and AEDT, while Brisbane stays on AEST and Perth uses AWST. A schedule that runs at 2:00 am locally can therefore shift relative to UTC during daylight saving changes.
This guide explains practical scheduling patterns for administrators, including command-line examples, logging methods, failure handling, and security considerations. The examples suit a small VPS, a business server in Sydney, or an internal Fedora host supporting systems across Australia.
Choosing Between Cron And Systemd Timers
Cron is a good fit for short, independent commands. Its five-field schedule is concise, familiar, and easy to deploy for tasks such as clearing temporary files or running a daily shell script. A user crontab is appropriate when the job does not require root privileges.
Systemd timers are generally better for services that need clear status information, dependencies, persistent execution, or controlled startup behaviour. A timer activates a corresponding service unit, allowing administrators to inspect results with systemctl and journalctl.
Writing Reliable Cron Jobs
Edit a user crontab with crontab -e, or manage the root schedule with sudo crontab -e. A daily backup at 1:30 am can be represented as:
30 1 * * * /usr/local/sbin/backup-files.sh >> /var/log/backup-files.log 2>&1
Use absolute paths because cron provides a limited environment. Set required variables explicitly, quote filenames, and make the script executable with chmod 750. A script should return a meaningful exit code so monitoring tools can detect failure.
Cron does not automatically load the interactive shell configuration used by an administrator. Define PATH, HOME, and application settings within the script or crontab. For an application server, review the Fedora LAMP setup before scheduling database dumps or web-directory maintenance.
Building A Systemd Timer
A systemd timer uses two unit files. The service describes the command, while the timer defines when it runs. For example, create /etc/systemd/system/report-cleanup.service:
[Unit]
Description=Clean old report files
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/report-cleanup.sh
Then create /etc/systemd/system/report-cleanup.timer:
[Unit]
Description=Run report cleanup daily
[Timer]
OnCalendar=*-*-* 01:30:00
Persistent=true
[Install]
WantedBy=timers.target
Load and enable the units with sudo systemctl daemon-reload, sudo systemctl enable --now report-cleanup.timer. The Persistent=true setting runs a missed job after the machine returns, which is useful for laptops and intermittently powered virtual machines.
Handling Time Zones And Missed Runs
Cron and systemd use the host’s configured time zone unless a job specifies another arrangement. Check it with timedatectl, then set a deliberate policy using sudo timedatectl set-timezone Australia/Sydney where appropriate. For systems serving Brisbane or Perth offices, use the actual operating location rather than assuming Sydney time.
Schedules around daylight saving transitions deserve testing. A task scheduled during a skipped hour may not run, while a repeated hour can create duplicate execution. For billing, payroll, and end-of-financial-year processing, UTC-based scheduling with explicit reporting conversion is often safer.
Logging, Locking And Security
Systemd services send output to the journal by default. Inspect recent runs with:
systemctl status report-cleanup.service
journalctl -u report-cleanup.service --since today
Cron jobs should redirect standard output and errors to a controlled log, then use logrotate to prevent unrestricted growth. Keep scripts outside writable web directories, restrict ownership to root where possible, and avoid placing passwords directly in command lines or crontabs.
Use flock to prevent overlapping runs when a backup or import can exceed its interval:
*/15 * * * * flock -n /run/data-sync.lock /usr/local/sbin/data-sync.sh
For systemd, add ExecStartPre=/usr/bin/flock -n /run/data-sync.lock /usr/bin/true or use a dedicated locking mechanism in the script.
Testing And Troubleshooting Scheduled Jobs
Run the command manually as the same user before scheduling it. Then verify syntax, permissions, path assumptions, network access, and SELinux policy. On Fedora and RHEL, inspect denials with ausearch -m AVC -ts recent when a script works interactively but fails under a service context.
For cron, check the distribution’s mail or logging configuration and review /var/log/cron or the system journal. For timers, use systemctl list-timers --all, systemctl cat report-cleanup.timer, and systemctl show report-cleanup.timer to confirm the loaded configuration.
Common faults include a missing executable bit, a different working directory, expired credentials, overlapping instances, and a server clock that is not synchronised. Confirm NTP status with timedatectl status, especially on cloud hosts connected through variable NBN links or regional networks.
Practical Scheduling Recommendations
A predictable scheduled-task policy makes maintenance easier during Australian business hours and planned overnight windows in Sydney, Melbourne, or Adelaide.
- Use cron for simple, portable commands with minimal dependencies.
- Use systemd timers for jobs requiring status, persistence, dependencies, or journal logging.
- Define absolute command paths and a controlled environment in every script.
- Record failures and protect logs with rotation, ownership, and appropriate permissions.
- Prevent overlapping executions with
flockor application-level locking. - Document the intended time zone, especially when daylight saving affects operations.
- Test missed-run and reboot behaviour before relying on a production schedule.
Cron And Systemd Timer Comparison
Both schedulers can run recurring commands, but their operational visibility differs. The following comparison helps match the mechanism to the task.
| Capability | Cron | systemd Timer |
|---|---|---|
| Configuration | Compact crontab entry | Separate timer and service units |
| Logging | Mail, files, or system logs | Integrated with journalctl |
| Missed execution after shutdown | Usually skipped | Supported with Persistent=true |
| Dependencies | Limited | Native systemd ordering and requirements |
| Status inspection | Basic | Detailed systemctl and timer views |
| Portability | Very high | Best on systemd-based distributions |
A good migration path is to keep the shell script independent, create a service unit for the command, and then add a timer for scheduling. This preserves a tested executable while improving observability and failure handling.
For everyday administration, choose the simplest mechanism that meets the reliability requirement: use cron for straightforward housekeeping, and use a systemd timer when reboot recovery, dependency control, and clear audit information matter. Always document the host time zone, test the command manually, and verify the next scheduled run before leaving it unattended.