Cron is the standard task scheduler on Unix systems. It runs commands on a schedule: backups, mailings, log cleanup, and data synchronization. Understanding cron syntax and behavior is critical for reliable automation. This guide covers every aspect, from basic syntax to debugging and production practices. To generate schedules, use the Cron Generator on reChecker.
What is cron
Cron is a daemon that runs in the background and checks the job table (crontab) every minute. When the scheduled time matches, it runs the specified command. Cron does not restart jobs after a reboot—it is always active on the system.
Typical use cases:
- Backing up databases and files
- Sending reports and notifications
- Cleaning up temporary files and logs
- Synchronizing data between systems
- Running monitoring and check scripts
Crontab syntax
A job line consists of five time fields and a command:
* * * * * команда
│ │ │ │ │
│ │ │ │ └── день недели (0-7, 0 и 7 = воскресенье)
│ │ │ └──── месяц (1-12)
│ │ └────── день месяца (1-31)
│ └──────── час (0-23)
└────────── минута (0-59)Basic schedule examples
| Schedule | Meaning |
|---|---|
* * * * * | Every minute |
0 * * * * | At the start of every hour |
0 0 * * * | Every day at midnight |
0 9 * * 1-5 | At 9:00 on weekdays |
30 14 1 * * | On the 1th of every month at 14:30 |
0 0 1 1 * | At midnight on January 1 |
Special values
Asterisk * — any allowed value. * in the minute field means “every minute.”
Comma , — a list of values:
0 8,12,18 * * * # В 8:00, 12:00 и 18:00Hyphen - — a range:
0 9-17 * * 1-5 # Каждый час с 9 до 17 по буднямSlash / — a step:
*/5 * * * * # Каждые 5 минут
0 */2 * * * # Каждые 2 часа
0 0 */3 * * # Каждые 3 дня в полночьCombinations:
5,35 8-18 * * 1-5 # В 8:05, 8:35, 9:05, 9:35... с 8 до 18 по будням
0 0 1,15 * * # 1-го и 15-го числа в полночьNamed values (not supported everywhere)
Some cron implementations support mnemonics:
@reboot # При загрузке системы
@yearly # 0 0 1 1 * (раз в год)
@monthly # 0 0 1 * * (раз в месяц)
@weekly # 0 0 * * 0 (раз в неделю)
@daily # 0 0 * * * (раз в день)
@hourly # 0 * * * * (раз в час)Check whether your system supports them: man crontab.
Editing crontab
# Редактировать задания текущего пользователя
crontab -e
# Просмотр текущих заданий
crontab -l
# Удалить все задания
crontab -r
# Загрузить задания из файла
crontab cronfile.txt
# Задания другого пользователя (требуются права)
crontab -u www-data -eWhen crontab -e, the editor specified by the EDITOR or VISUAL variable opens. Saving and exiting applies the changes—you do not need to restart cron.
Environment variables
Cron runs commands in a minimal environment. PATH, HOME, and variables from .bashrc are often missing. Explicitly set what you need at the beginning of the crontab:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
HOME=/home/user
0 0 * * * /opt/scripts/backup.shMAILTO is the address to which output (stdout/stderr) is emailed. An empty value disables email.
Time zones
By default, cron uses the system time zone. To set a different one for a job:
CRON_TZ=Europe/Moscow
0 9 * * * /opt/scripts/report.shOr set TZ in the crontab environment variables. Make sure the system knows the required time zone: ls /usr/share/zoneinfo/.
Redirecting output
By default, cron emails output (if MAILTO is set) or sends it to syslog. To write it to a file:
0 0 * * * /opt/backup.sh >> /var/log/backup.log 2>&12>&1 redirects stderr to stdout. To keep them separate:
0 0 * * * /opt/backup.sh >> /var/log/backup.log 2>> /var/log/backup.errTo suppress all output:
0 0 * * * /opt/backup.sh > /dev/null 2>&1Common errors
Relative paths
Cron runs commands from the user's home directory (often /home/user). Use absolute paths:
# Неправильно
0 0 * * * ./script.sh
# Правильно
0 0 * * * /home/user/scripts/backup.shPATH
Commands such as node, php, and python3 may not be available if PATH is not set:
PATH=/usr/local/bin:/usr/bin:/bin
0 * * * * node /opt/app/cron.jsOr specify the full path: /usr/bin/node.
Execute permissions
The script must have execute permission: chmod +x script.sh. For interpreters, you can invoke them explicitly:
0 0 * * * /usr/bin/python3 /opt/scripts/task.pyPreventing overlapping runs
If a job takes longer than the interval, multiple instances may run in parallel. Use a lockfile:
#!/bin/bash
LOCKFILE=/tmp/backup.lock
if [ -f "$LOCKFILE" ]; then
exit 1
fi
trap "rm -f $LOCKFILE" EXIT
touch $LOCKFILE
# ... основная логикаOr use flock:
0 * * * * flock -n /tmp/backup.lock /opt/backup.sh-n — do not wait; exit with an error if the lock is held.
Logging and debugging
Enable logging in the script:
#!/bin/bash
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> /var/log/cron-task.log; }
log "Starting"
# ...
log "Finished"Check the cron logs (varies by distribution):
# Debian/Ubuntu
grep CRON /var/log/syslog
# CentOS/RHEL
grep CRON /var/log/cronTest manually with a cron-like environment:
env -i HOME=$HOME PATH=/usr/bin:/bin SHELL=/bin/bash /opt/script.shSecurity
- Least privilege — create a separate user for cron jobs with limited permissions
- Input validation — scripts should not trust environment variables without checking them
- Secrets — do not store passwords in crontab; use configuration files with restricted permissions (chmod 600)
- Auditing — regularly check
crontab -lfor suspicious jobs
Alternatives to cron
- systemd timers — integration with systemd and more flexible logging
- at — one-time execution at a specified time
- anacron — for systems that are not running 24/7 (laptops, desktops)
Web projects often use built-in schedulers: Laravel Scheduler, Celery Beat, and Sidekiq Cron. They are more convenient for applications, but require a continuously running process.
Practical cron examples for web developers are in the article 15 useful cron jobs for web developers. You can generate and validate schedules with the Cron Generator on reChecker.
Time conflicts and cron
Cron runs jobs according to system time. If the server is in UTC but the business logic is based on local time (for example, Moscow time), you need to account for the difference. Use CRON_TZ or the TZ variable in crontab:
CRON_TZ=Europe/Moscow
0 9 * * 1-5 /opt/send-report.shThe job will run at 9:00 Moscow time. For scripts that handle dates themselves, make sure they use the correct time zone or get it from environment variables.
Error notifications
By default, cron emails output (if MAILTO is set) or discards it. To send alerts on errors, check the exit code:
#!/bin/bash
/opt/backup.sh
if [ $? -ne 0 ]; then
echo "Backup failed" | mail -s "Cron alert" admin@example.com
exit 1
fiOr use ||:
0 3 * * * /opt/backup.sh || echo "Backup failed" | mail -s "Alert" admin@example.comLogging in cron
A standard approach is to redirect output to a file with the date in its name:
0 0 * * * /opt/daily.sh >> /var/log/daily_$(date +\%Y\%m\%d).log 2>&1Use logrotate or built-in script logic to rotate logs (deleting files older than N days).
Cron and permissions
Jobs run as the user who owns the crontab. Web applications often use the www-data or nginx user. Make sure the user has permission to read the scripts and write to the required directories:
# Проверка прав
ls -la /opt/scripts/backup.sh
# Должен быть исполняем для владельца или группы
chmod 750 /opt/scripts/backup.shWorking with systemd
On systems with systemd, cron and systemd timers can coexist. Timers offer more flexible logging and integration with journald. To migrate a cron job to systemd:
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.targetSummary
Cron remains a simple and reliable tool for recurring tasks. Key points: use absolute paths, set PATH explicitly, use a lockfile for long-running jobs, and log and monitor errors. For more complex use cases, consider systemd timers or schedulers built into applications.