Cron в Linux: синтаксис расписания, crontab -e и примеры
Коротко
Cron в Linux запускает команды и скрипты по расписанию. Задания записываются в crontab командой crontab -e, по одному на строку: пять полей времени (минута, час, день месяца, месяц, день недели) и команда. Например, строка */5 * * * * /usr/bin/php /var/www/site/cron.php выполняет PHP-скрипт каждые 5 минут. Ниже синтаксис cron с примерами, запуск PHP и где смотреть логи, если задание не срабатывает.
Содержание
Как устроен cron
Cron это служба (демон), которая раз в минуту просыпается, читает таблицы заданий и запускает те, чьё время наступило. Своя таблица (crontab) есть у каждого пользователя, плюс системные файлы. В Ubuntu и Debian служба называется cron, в CentOS, Rocky Linux, AlmaLinux и Fedora она называется crond (пакет cronie), в Astra Linux используется тот же cron, что и в Debian.

Где лежат задания:
| Место | Чьи задания | Особенность |
|---|---|---|
crontab -e | Текущего пользователя | Хранится в /var/spool/cron/crontabs/, руками не править |
/etc/crontab | Системные | Шестое поле: от какого пользователя запускать |
/etc/cron.d/ | Задания пакетов и ваши файлы | Формат как у /etc/crontab |
/etc/cron.daily/, .hourly, .weekly | Скрипты без расписания | Запускаются раз в день, час, неделю |
Проверить, что служба работает, можно командой systemctl status cron (на RHEL-системах systemctl status crond). Строка "active (running)" значит, что всё в порядке.
Синтаксис расписания cron
Каждая строка crontab состоит из пяти полей времени и команды. Поля разделяются пробелами:
┌──────── минута (0-59)
│ ┌────── час (0-23)
│ │ ┌──── день месяца (1-31)
│ │ │ ┌── месяц (1-12 или jan-dec)
│ │ │ │ ┌ день недели (0-7, где 0 и 7 это воскресенье, или sun-sat)
│ │ │ │ │
* * * * * команда
Специальные символы в полях:
*любое значение: "каждую минуту", "каждый час".,список:1,15в поле дня означает 1-е и 15-е число.-диапазон:1-5в поле дня недели означает с понедельника по пятницу./шаг:*/10в поле минут означает каждые 10 минут,0-30/5каждые 5 минут в первые полчаса.
Если заданы и день месяца, и день недели (оба не *), cron срабатывает, когда совпадает любое из них. Строка 0 9 1 * 1 выполнится 1-го числа и ещё каждый понедельник, а не только в понедельник, выпавший на 1-е.
Сокращения @reboot, @daily и другие
Вместо пяти полей можно написать одно слово:
| Запись | То же самое | Когда |
|---|---|---|
@reboot | нет аналога | Один раз после загрузки системы |
@hourly | 0 * * * * | Каждый час в 00 минут |
@daily | 0 0 * * * | Каждый день в полночь |
@weekly | 0 0 * * 0 | По воскресеньям в полночь |
@monthly | 0 0 1 * * | 1-го числа в полночь |
Примеры расписания cron
Готовые cron-выражения для частых задач. Подставьте свою команду вместо команда.
| Выражение | Когда выполняется |
|---|---|
* * * * * | Каждую минуту |
*/5 * * * * | Каждые 5 минут |
*/10 * * * * | Каждые 10 минут |
0 * * * * | Каждый час, в начале часа |
30 */2 * * * | Каждые 2 часа в 30 минут |
0 3 * * * | Ежедневно в 03:00 |
0 1 * * * | Ежедневно в 01:00 (в выдаче часто как "cron 0 1") |
0 9-18 * * 1-5 | Каждый час с 9 до 18 по будням |
0 0 * * 0 | Раз в неделю, в воскресенье в полночь |
0 2 1 * * | 1-го числа каждого месяца в 02:00 |
0 0 1 1 * | Раз в год, 1 января |
Cron не умеет запускать задания чаще раза в минуту. Если нужен запуск каждые 30 секунд, поставьте две строки, во второй добавьте задержку: * * * * * sleep 30; команда. Для таких частот лучше подходит постоянно работающий процесс (воркер очереди) или таймер systemd.
Проверить выражение перед сохранением удобно в онлайн-сервисе crontab.guru: он переводит строку в человеческий текст и показывает ближайшие запуски.
Как редактировать crontab
Своё расписание пользователь редактирует командой crontab -e. При первом запуске система спросит, каким редактором пользоваться; новичкам проще выбрать nano.
- Подключитесь к серверу по SSH под тем пользователем, от чьего имени должен работать скрипт.
- Выполните
crontab -e. - Если появился выбор редактора, введите номер пункта с
/bin/nanoи нажмите Enter. - Перейдите в конец файла и допишите строку задания.
- Сохраните файл в nano сочетанием Ctrl + O, затем Enter.
- Выйдите из nano сочетанием Ctrl + X. Сообщение "crontab: installing new crontab" значит, что расписание принято.

Если открылся vim, нажмите I для режима ввода, допишите строку, затем Esc, наберите :wq и нажмите Enter. Выйти без сохранения: :q!. Сменить редактор навсегда можно командой select-editor или переменной EDITOR=nano crontab -e.

Другие команды crontab
crontab -l # показать свои задания
crontab -l > ~/cron.bak # сохранить копию расписания в файл
crontab ~/cron.bak # загрузить расписание из файла (заменит текущее)
sudo crontab -e # задания пользователя root
sudo crontab -u www-data -e # задания другого пользователя
crontab -r # удалить ВСЁ расписание без подтверждения
Клавиши e и r стоят рядом. crontab -r удаляет все задания сразу и без вопросов, поэтому держите копию из crontab -l. Перезапускать cron после crontab -e не нужно: служба сама замечает изменения. Перезапуск (sudo systemctl restart cron) имеет смысл только после смены часового пояса или правки настроек самой службы.
Запуск PHP-скрипта по cron
Самая частая задача веб-разработчика: выполнять PHP-скрипт по расписанию (рассылка, очистка старых записей, выгрузка товаров). В cron пишут полный путь к интерпретатору и к файлу, потому что окружение у cron минимальное и папки из вашего PATH он может не знать.
# Узнать путь к PHP
which php # /usr/bin/php
php -v # версия CLI
# Если на сервере несколько версий, указывайте нужную явно
ls /usr/bin/php* # /usr/bin/php8.3 /usr/bin/php8.4 ...
Строка в crontab для запуска скрипта каждые 15 минут с записью вывода в лог:
*/15 * * * * cd /var/www/site && /usr/bin/php8.4 cron/cleanup.php >> /var/log/site-cron.log 2>&1
Здесь cd переходит в папку сайта, чтобы относительные пути в скрипте работали так же, как при ручном запуске. >> файл дописывает вывод в лог, а 2>&1 отправляет туда же ошибки. Папка лога должна быть доступна на запись пользователю, от которого запускается задание.
Пример скрипта для cron
Скрипт удаляет просроченные токены сброса пароля из базы. Он не даёт запустить себя из браузера и пишет итог в стандартный вывод, который попадёт в лог:
<?php
declare(strict_types=1);
// Запуск только из командной строки
if (PHP_SAPI !== 'cli') {
http_response_code(403);
exit('Forbidden');
}
date_default_timezone_set('Europe/Moscow');
$pdo = new PDO(
'mysql:host=localhost;dbname=shop;charset=utf8mb4',
'shop_cron',
getenv('DB_PASSWORD') ?: '',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
$stmt = $pdo->prepare('DELETE FROM password_resets WHERE created_at < :limit');
$stmt->execute(['limit' => date('Y-m-d H:i:s', strtotime('-1 day'))]);
echo date('Y-m-d H:i:s'), ' удалено записей: ', $stmt->rowCount(), PHP_EOL;
Подключение к базе здесь сделано через подготовленный запрос, подробнее о нём в статье про PDO в PHP. Учтите, что у консольного PHP может быть свой php.ini, отдельный от того, что использует сайт: лимиты памяти, часовой пояс и включённые расширения бывают разными. Как найти нужный файл, рассказано в статье где находится php.ini, а работа с датами и часовыми поясами в скриптах разобрана в материале про дату и время в PHP.
Защита от двойного запуска
Если скрипт иногда работает дольше интервала, следующий запуск начнётся поверх предыдущего. Утилита flock не даст запустить вторую копию, пока работает первая:
*/5 * * * * flock -n /tmp/export.lock /usr/bin/php /var/www/site/cron/export.php >> /var/log/export.log 2>&1
Laravel и WordPress
В Laravel достаточно одной строки cron, а само расписание описывается в коде (routes/console.php):
* * * * * cd /var/www/app && php artisan schedule:run >> /dev/null 2>&1
В WordPress встроенный wp-cron.php запускается при заходах посетителей: на сайте без трафика задачи не выполняются, а на нагруженном лишний раз тратят ресурсы. Отключите его строкой define('DISABLE_WP_CRON', true); в wp-config.php и вызывайте из системного cron:
*/10 * * * * cd /var/www/wp && /usr/bin/php wp-cron.php > /dev/null 2>&1
Cron на виртуальном хостинге
На хостинге без SSH задания добавляют в панели управления, в разделе с названием вроде "Планировщик заданий" или "CRON": выбираете время из списков или вводите выражение, а в поле команды указываете путь к PHP нужной версии из подсказки хостинга и полный путь к скрипту от корня аккаунта. Если панель позволяет только открыть URL, используйте curl -s https://site.ru/cron.php?key=..., а в скрипте проверяйте длинный секретный ключ, чтобы задание не мог запустить посторонний.
Логи cron: как узнать, запускалось ли задание
Сам факт запуска cron записывает в системный журнал. Вывод команды туда не попадает, его нужно перенаправлять в свой файл, как в примерах выше.
# Ubuntu и Debian
grep CRON /var/log/syslog | tail -20
# Через journald (любой дистрибутив с systemd)
journalctl -u cron --since "1 hour ago" # в RHEL-системах -u crond
# CentOS, Rocky, AlmaLinux
sudo tail -f /var/log/cron

Если вывод команды не перенаправлен, cron пытается отправить его письмом владельцу задания. Переменная MAILTO в начале crontab задаёт адрес; строка MAILTO="" отключает письма полностью. Без настроенной почты на сервере письма просто теряются, поэтому надёжнее писать в файл.
Почему cron не запускает задание
| Причина | Как исправить |
|---|---|
| Команда не найдена: в cron короткий PATH | Писать полные пути: /usr/bin/php, /usr/local/bin/composer |
| Скрипт работает вручную, но не в cron | Добавить cd в папку проекта, задать переменные окружения в crontab |
Символ % в команде обрезает строку | Экранировать: date +\%Y-\%m-\%d |
| Нет перевода строки после последнего задания | Оставить пустую строку в конце crontab |
| Нет прав на файл или лог | Запускать от владельца сайта, а не от root, проверить права папки лога |
| Время запуска "не то" | Проверить часовой пояс сервера командой timedatectl |
Файл в /etc/cron.d/ игнорируется | Убрать точку и расширение из имени файла, указать пользователя шестым полем |
Чтобы воспроизвести окружение cron при отладке, запустите команду с почти пустым набором переменных: env -i /bin/sh -c 'cd /var/www/site && /usr/bin/php cron/cleanup.php'. Если в таком виде скрипт падает, причина в окружении. Ошибки самого PHP удобнее видеть, если в консольном скрипте включён вывод ошибок; как это сделать, показано в статье про вывод ошибок PHP.
Переменные окружения в crontab
В начале crontab можно задать переменные, которые получат все задания ниже:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=""
DB_PASSWORD=секретный_пароль
0 4 * * * /usr/bin/php /var/www/site/cron/report.php >> /var/log/report.log 2>&1
Подстановка вида $HOME/bin в этих строках не работает: значения берутся как есть.
Cron или таймеры systemd
На современных дистрибутивах наряду с cron есть таймеры systemd. Они удобнее, когда нужно видеть каждое выполнение в journalctl, догонять пропущенные запуски после выключения сервера (Persistent=true) или ограничивать память и процессор задания. Для обычных задач сайта cron проще: одна строка, и всё работает. Если проект живёт в Docker, задания либо запускают с хоста через docker compose exec, либо выносят в отдельный контейнер; варианты есть в статье про Docker для PHP.
Частые вопросы
Как запустить задание cron каждую минуту?
Запишите в crontab строку * * * * * команда. Пять звёздочек значат "каждую минуту, каждого часа, каждого дня".
Как настроить cron каждые 5 минут?
Используйте шаг в поле минут: */5 * * * * команда. Так же записываются каждые 10 (*/10) и 15 минут (*/15).
Как сохранить изменения после crontab -e?
В nano нажмите Ctrl + O, Enter и Ctrl + X, в vim наберите :wq. Сообщение "installing new crontab" подтверждает сохранение.
Где лежит файл crontab?
Таблицы пользователей хранятся в /var/spool/cron/crontabs/ (в RHEL-системах /var/spool/cron/), но править их нужно только через crontab -e. Системные задания лежат в /etc/crontab и /etc/cron.d/.
Где смотреть логи cron?
В Ubuntu выполните grep CRON /var/log/syslog или journalctl -u cron, в CentOS и AlmaLinux смотрите /var/log/cron. Вывод самой команды сохраняйте в свой файл через >> файл 2>&1.
Нужно ли перезапускать cron после изменения crontab?
Нет, служба сама подхватывает изменения из crontab -e. Перезапуск командой sudo systemctl restart cron нужен только после смены часового пояса или настроек службы.



