EAST4SERV / SEARCH

ما الذي تبحث عنه؟

InsightsLinux Administration
Linux Administration

Cron vs systemd Timers: Schedule Server Jobs Safely

Scheduled work often survives its first release but fails after a reboot, timezone change, or missed maintenance window. Both cron and systemd timers can run a command periodically...

SCHEDULE to JOB IDENTITY to RESULT CHECK workflow diagram
Original East4Serv technical workflow for Cron vs systemd Timers: Schedule Server Jobs Safely
Share this article

Scheduled work often survives its first release but fails after a reboot, timezone change, or missed maintenance window. Both cron and systemd timers can run a command periodically; neither makes a job safe to retry or ensures the command's business effect happened exactly once. Choosing between them starts with the job's required schedule, execution context, logs, and missed-run policy.

This guide compares a user crontab with systemd timers on Linux. Cron implementations differ, especially around extensions such as @reboot, random delay, and timezone support. Examples are illustrative; review the documentation installed on your distribution before changing a production schedule.

Prerequisites and workload inventory

Identify the job owner, command, working directory, environment variables, credentials, typical runtime, and side effects. A report-generation job can often be retried safely. A billing capture, domain registration, or provisioning task must use application-level idempotency and reconciliation regardless of scheduler. Record whether the job should run after a host was powered off during its normal schedule.

Inspect existing schedules before adding another mechanism, or you may execute the same job twice:

crontab -l
systemctl list-timers --all --no-pager
systemctl status cron --no-pager

On some distributions the cron daemon is named crond. Listing your own crontab does not show root or other users' schedules. Review /etc/crontab, /etc/cron.d/, and application deployment configuration with appropriate access.

Step 1: Understand a cron entry

A traditional user crontab has five time fields followed by a command. This example would run at 02:15 each day, under the crontab owner's identity:

15 2 * * * /usr/local/bin/example-report --dry-run

The script path should be absolute. Set only the environment variables the job needs; cron's environment is smaller than an interactive login shell. Capture errors to an approved logging destination and configure a mail recipient where appropriate. A scheduler invoking the command says nothing about whether the output was valid, so monitor both execution and application result.

Cron normally evaluates schedules by the host's local time. Daylight-saving transitions can skip a nonexistent local minute or run a repeated local minute twice, depending on implementation. Prefer UTC schedules for globally coordinated jobs when that matches the business requirement, and test calendars explicitly.

Step 2: Model the same job as a systemd service and timer

A systemd timer activates a named service. The service describes identity, command, and working directory; the timer describes when it runs. The following files are examples, not a deployment command to paste onto a live host:

# /etc/systemd/system/example-report.service
[Unit]
Description=Example report dry run

[Service]
Type=oneshot
User=reporter
WorkingDirectory=/srv/example
ExecStart=/usr/local/bin/example-report --dry-run
# /etc/systemd/system/example-report.timer
[Unit]
Description=Schedule example report

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

[Install]
WantedBy=timers.target

Persistent=true asks a calendar timer to catch up after a missed run while the timer was inactive. That can be valuable for reports and dangerous for a non-idempotent payment or provisioning task. Confirm whether the service can safely run late before enabling it. A systemd timer also has accuracy and randomized-delay settings; its nominal time is not a strict real-time execution guarantee.

Step 3: Validate one mechanism, then enable it

Do not leave cron and timer active for the same work. After reviewing service identity, paths, and application idempotency, validate the unit files and calendar expression in a test environment:

systemd-analyze verify /etc/systemd/system/example-report.service
systemd-analyze calendar '*-*-* 02:15:00'
systemctl list-timers --all --no-pager

Changing unit files requires a systemctl daemon-reload and then an approved enable/start operation. systemctl status example-report.timer tells you whether the timer is active; journalctl -u example-report.service shows runs and failures. The service can exit successfully while producing an incorrect report, so add application-specific verification.

Expected result and troubleshooting

Exactly one scheduler owns the job, its identity and environment are documented, the next scheduled run is visible, and failed executions are detected. If a job works in a shell but not from cron, inspect PATH, working directory, permissions, and input assumptions. If a timer never fires, inspect whether it is enabled and active, whether the calendar expression matches the expected timezone, and whether the host clock is synchronized. If it runs after reboot unexpectedly, review Persistent=true and missed-run state.

Security considerations

Do not schedule privileged scripts as root by default. Keep credentials out of command arguments and public logs. Separate schedule changes from application release changes where possible, and audit who changed the timing. Limit concurrent runs with application-level locks or service design; blindly adding a shell lock around a payment task does not create exactly-once semantics.

FAQ

Is a systemd timer always better than cron?

No. A simple portable cron schedule may be enough. Timers integrate with service identity and journal output, but the operator must understand unit lifecycle and catch-up behavior.

Does Persistent=true replay every missed occurrence?

No. It can trigger a catch-up activation after inactivity for calendar timers; it is not a durable queue of every missed business event.

Can I use both for redundancy?

Not for the same non-idempotent job. That risks duplicate effects. Use monitored failover and idempotency instead.

Continue reading

Related guides cover Laravel queues and scheduling, service failures after reboot, and backup restore drills. East4Serv server management can include a reviewed scheduling and alerting scope.

References: systemd timer manual, systemd service manual, and crontab manual. Examples are illustrative and require review on the target distribution.

cronsystemd timersScheduling