Linux Tutorial / Schedule Tasks with cron and systemd Timers

Cron suits simple schedules, while systemd timers integrate scheduled work with service state and logs. Validate the interpreted schedule, actual execution, output, and failures separately instead of treating registration as proof of success.

Test a command directly, as in Bash script basics, before scheduling it. Verify the user systemd manager’s logout behavior and linger configuration in the actual VM; registering a timer alone does not guarantee continued execution.

System configuration exercises use a conventional Ubuntu 26.04 LTS or Rocky Linux 9 VM as the reference environment. Containers, WSL, and other releases can differ in service and package configuration. Prepare console recovery and record your versions using the virtual machine setup lesson.

Choose between cron and a systemd timer

Criterion cron systemd timer
Configuration Time fields plus a command Separate timer and service units
Verification Output and distribution-specific logs Service state and journal
Environment Different from an interactive shell Environment defined for the unit
Missed runs Traditional cron generally does not catch up Consider OnCalendar with Persistent

Daemon names and packages vary: Ubuntu commonly uses cron, while Rocky Linux uses cronie and crond. The timer example requires an available systemd user manager. Distinguish traditional cron behavior from complementary tools such as anacron.

Read cron fields and execution context

crontab -e edits the current user’s schedule. A user crontab has minute, hour, day-of-month, month, and weekday fields before the command. The example runs daily at 02:15; replace /home/USER with actual absolute paths. System /etc/crontab entries also include a user field.

15 2 * * * /bin/bash /home/USER/bin/job.sh >> /home/USER/job.log 2>&1

Cron does not inherit your interactive terminal’s PATH, working directory, and variables unchanged. Use absolute paths, set working directories explicitly, and keep secrets out of crontab text. Restricting both day-of-month and weekday can invoke OR-style matching. Check the implementation’s timezone, daylight-saving, and percent-character rules.

Create complete user service and timer units

Do not overwrite units with these names if they already exist. The example writes a timestamp to the user journal every minute without creating a root service. Confirm /usr/bin/date with command -v date and adjust ExecStart if your installation differs.

mkdir -p "$HOME/.config/systemd/user"
cat > "$HOME/.config/systemd/user/linux-course-clock.service" <<'EOF'
[Unit]
Description=Linux course timestamp exercise

[Service]
Type=oneshot
ExecStart=/usr/bin/date --iso-8601=seconds
EOF
cat > "$HOME/.config/systemd/user/linux-course-clock.timer" <<'EOF'
[Unit]
Description=Run the course clock every minute

[Timer]
OnCalendar=*-*-* *:*:00
AccuracySec=1s
Persistent=true

[Install]
WantedBy=timers.target
EOF
systemd-analyze calendar '*-*-* *:*:00'
systemctl --user daemon-reload
systemctl --user enable --now linux-course-clock.timer

A timer activates the service with the matching base name. OnCalendar defines a calendar schedule; AccuracySec controls coalescing tolerance, not a hard real-time guarantee. With Persistent=true, an overdue calendar timer can trigger on reactivation, but missed occurrences are not all replayed individually.

Inspect the next trigger and the actual result

systemctl --user list-timers --all linux-course-clock.timer
systemctl --user status linux-course-clock.timer
journalctl --user -u linux-course-clock.service --since "5 minutes ago" --no-pager
systemctl --user show linux-course-clock.service -p Result -p ExecMainStatus
timedatectl

Inspect the next trigger, then check journal output after one or two minutes. A oneshot service can be inactive after a successful run, so read Result and ExecMainStatus as well. Use timedatectl to compare the server timezone and clock synchronization with the intended business schedule.

For jobs that must survive logout, inspect the user manager’s lifecycle and the site’s lingering policy. Enabling a timer does not establish behavior across every logout or reboot condition. Production system timers need a deliberate service account, paths, privileges, and resource limits.

Control overlap, inspect failures, and remove the exercise

A cron job that exceeds its interval can overlap with the next invocation; consider locking such as flock where appropriate. A timer does not automatically create a second concurrent instance of the same service when it is already active. Other units or manual invocations can still share resources, so application-level concurrency requirements remain important.

systemctl --user disable --now linux-course-clock.timer
rm -- "$HOME/.config/systemd/user/linux-course-clock.timer" "$HOME/.config/systemd/user/linux-course-clock.service"
systemctl --user daemon-reload
systemctl --user list-timers --all linux-course-clock.timer

Removal targets only the two lab units. If you added the sample cron entry, remove only that entry with crontab -e and verify with crontab -l; do not delete the entire schedule. Production automation also needs a way to detect failure or nonexecution and recover from it.

Official references