Cron is the standard job scheduler in Linux, found in every infrastructure. Jobs pile up, logs accumulate, and the environment breaks things. Let’s walk through how to configure cron reliably and where it falls short.
When to Use Cron and When to Avoid It
Cron fits simple recurring tasks: backups, log rotation, temp file cleanup, periodic notifications. It’s a daemon that sleeps between runs — no resource consumption.
Avoid cron for:
tasks requiring millisecond precision (cron fires at the minute level)
tasks with hard dependencies on other services (use systemd units with After=)
long-running processes that could overlap (you need locking)
Anatomy of a Crontab Entry
Format:
* * * * * command
- - - - -
| | | | |
| | | | └── day of week (0-7, 0 and 7 = Sunday)
| | | └──── month (1-12)
| | └────── day of month (1-31)
| └──────── hour (0-23)
└────────── minute (0-59)
Special values:
@reboot — at boot
@yearly — once a year (0 0 1 1 *)
@monthly — once a month (0 0 1 * *)
@weekly — once a week (0 0 * * 0)
@daily — once a day (0 0 * * *)
@hourly — once an hour (0 * * * *)
Examples:
0 3 * * * /opt/scripts/backup.sh # daily at 03:00
15,45 * * * * /usr/local/bin/check.sh # every 15 and 45 minutes
0 */4 * * * /opt/metrics/collect.sh # every 4 hours
0 9-17 * * 1-5 /opt/reports/daily.sh # hourly during business hours on weekdays
crontab -e and crontab -l: Common Commands
crontab-l# show current user crontabcrontab-e# edit crontab (opens in EDITOR)crontab-r# remove crontab (no confirmation!)crontab-l-uusername# view another user's crontab (from root)crontabfilename# load jobs from file
Note
Default editor is vi. Change it: export EDITOR=nano.
Where System Schedules Live
Beyond user crontabs, there are system files:
/etc/crontab# system crontab (format differs — includes username field)/etc/cron.d/# drop-in directory/etc/cron.daily/# daily jobs (run-parts)/etc/cron.hourly/# hourly jobs/etc/cron.monthly/# monthly jobs/etc/cron.weekly/# weekly jobs/var/spool/cron/crontabs/# user crontab files
Lines in /etc/crontab and /etc/cron.d/* include a username field:
#!/bin/bash
# /opt/scripts/run_backup.shsource /etc/profile
cd /opt/project ||exit1./backup.sh
Tip
Always verify variables: env | sort in terminal vs. job * * * * * env | sort > /tmp/cron_env.txt.
Output Redirection and Log Rotation
By default, cron emails stdout and stderr to the user. Set MAILTO="" to disable.
# send output to file03***/opt/scripts/backup.sh>>/var/log/backup.log2>&1# add timestamp to log (readability)03***/opt/scripts/backup.sh>>/var/log/backup.log2>&1# rotate old logs03***/opt/scripts/backup.sh>>/var/log/backup.log2>&1&& \
find/var/log-name"backup.log*"-mtime+7-delete
# show next run time for each jobfor f in /etc/cron.d/*;doif[ -f "$f"];thenecho"=== $f ===" head -1 "$f"# nearest run timenext=$(echo"0 3 * * *"| sed 's/\*/0/g'| xargs -I{} date -d "{}"'+%Y-%m-%d %H:%M')echo"Next: $next"fidone# dry runcat /etc/cron.d/my-task | grep -v "^#"| grep -v "^$"|whileread schedule cmd;doecho"Would run: $cmd"done
# Remove job- name:Remove old cron jobcommunity.general.cron:name:"obsolete task"state:absentuser:"root"
# Drop a file into /etc/cron.d/- name:Deploy cron fileansible.builtin.copy:src:files/my-cron-jobdest:/etc/cron.d/my-cron-jobowner:rootgroup:rootmode:"0644"notify:restart cron
systemd Timers as an Alternative to Cron
Timers are more precise, support service dependencies, randomiseddelaysec, and calendar specs.