Cron: The Backbone of Server Automation

Cron is the UNIX scheduler that runs commands at fixed times. On an Ubuntu VPS it drives log rotation, certificate renewals, backups, database maintenance, and thousands of custom scripts. This guide covers scheduling, debugging, locking, and monitoring cron jobs on Ubuntu 22.04 LTS and Ubuntu 24.04 LTS.

Cron Installation and Status

Ubuntu ships cron preinstalled. Confirm it's running:

systemctl status cron
apt install -y cron   # only if missing

Each user has their own crontab. Edit the current user's with:

crontab -e

System-wide jobs live in /etc/crontab and the drop-in directories /etc/cron.d/, /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, and /etc/cron.monthly/.

Cron Syntax

Each line has five time fields followed by the command:

# m   h   dom mon dow   command
  */5 *   *   *   *     /usr/local/bin/healthcheck.sh
  0   3   *   *   *     /usr/local/bin/backup.sh
  30  2   *   *   0     /usr/local/bin/weekly-report.sh
FieldRange
Minute0-59
Hour0-23
Day of month1-31
Month1-12
Day of week0-7 (0 and 7 are Sunday)

Shortcuts include @reboot, @hourly, @daily, @weekly, @monthly, and @yearly.

System vs User Crontabs

Files under /etc/cron.d/ have an extra user field between the time and the command:

# /etc/cron.d/myapp
*/10 * * * * deploy /usr/local/bin/queue-worker.sh

Always include a newline at the end of cron.d files - cron silently skips the last line without it.

Environment Gotchas

Cron runs commands with a minimal environment. PATH is usually /usr/bin:/bin, and your shell aliases do not exist. Always use absolute paths:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
MAILTO=admin@example.com

0 4 * * * /usr/bin/python3 /opt/app/cleanup.py >> /var/log/cleanup.log 2>&1

The MAILTO directive emails stdout/stderr to the specified address if an MTA is configured.

Capturing Output and Logs

By default cron mails output. For logging to disk instead, redirect:

0 */6 * * * /opt/scripts/sync.sh >> /var/log/sync.log 2>&1

Rotate these logs with /etc/logrotate.d/cron-custom to stop them growing without bound.

Preventing Overlapping Runs

Long-running jobs can overlap if the previous run hasn't finished. Use flock to serialize them:

*/5 * * * * /usr/bin/flock -n /tmp/sync.lock /opt/scripts/sync.sh

The -n flag fails immediately if another instance holds the lock. Add || true if you want cron to consider the skipped run a success.

Monitoring Cron Jobs

Cron itself rarely alerts on failures. Three patterns help:

A minimal heartbeat wrapper:

#!/bin/bash
set -euo pipefail
PING_URL="https://hc-ping.com/your-uuid"
"$@"
curl -fsS --retry 3 "$PING_URL" > /dev/null

Systemd Timers as a Modern Alternative

Systemd timers offer better logging, dependency management, and randomized delays. A timer + service pair for nightly backups:

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh

# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup nightly
[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=30m
Persistent=true
[Install]
WantedBy=timers.target

Enable with systemctl enable --now backup.timer and inspect with systemctl list-timers.

Debugging a Failing Cron Job

  1. Tail the log: grep CRON /var/log/syslog.
  2. Run the command manually under cron's environment: env -i PATH=/usr/bin:/bin /bin/bash -c '/path/to/script.sh'.
  3. Check file permissions, script shebangs, and line endings (CRLF breaks cron scripts).
  4. Confirm the service is enabled on boot: systemctl is-enabled cron.

Common Cron Patterns

Typical jobs you'll schedule on a production Ubuntu VPS:

Running production Ubuntu servers? MassiveGRID's Cloud VPS provides NVMe storage, high CPU burst, and guaranteed network performance ideal for background cron workloads. For fully managed scheduling and maintenance windows, explore our Managed Cloud Servers or contact our team.

Published by MassiveGRID - cloud hosting with 24/7 operations and managed scheduled workloads.