Перейти к основному содержимому

Crontab в Linux

·1030 слов·5 минут
DevOps • Networks • Security • Infrastructure
Автор
DevOps • Networks • Security • Infrastructure
DevOps/Network/Infra Engineer, CyberSecurity Expert

cron — это стандартный планировщик задач в Linux. С его помощью можно автоматически запускать команды и скрипты:

  • каждые несколько минут;
  • каждый час;
  • каждый день;
  • по определённым дням недели;
  • при загрузке системы.

Например, cron удобно использовать для:

  • резервного копирования;
  • очистки временных файлов;
  • проверки состояния сервисов;
  • запуска скриптов мониторинга;
  • синхронизации файлов;
  • перезапуска служб при определённых условиях.

В этой статье разберём, как пользоваться crontab на практике.

Что такое cron и crontab
#

В Linux за выполнение задач по расписанию обычно отвечает служба cron.

Проверить её состояние можно командой:

systemctl status cron

На некоторых дистрибутивах служба называется crond:

systemctl status crond

crontab — это таблица заданий пользователя, которую читает cron.

Каждый пользователь может иметь собственный набор задач.

Открыть crontab текущего пользователя:

crontab -e

Посмотреть текущие задания:

crontab -l

Удалить все задания текущего пользователя:

crontab -r

После сохранения файла вручную перезапускать cron обычно не требуется. Изменения подхватываются автоматически.

Формат crontab
#

Строка задания выглядит так:

* * * * * команда
│ │ │ │ │
│ │ │ │ └── день недели
│ │ │ └──── месяц
│ │ └────── день месяца
│ └──────── час
└────────── минута

Полный формат:

минута час день_месяца месяц день_недели команда

Диапазоны:

Поле Значения
Минута 0-59
Час 0-23
День месяца 1-31
Месяц 1-12
День недели 0-7

Для дня недели:

0 или 7 — воскресенье
1 — понедельник
2 — вторник
3 — среда
4 — четверг
5 — пятница
6 — суббота

Частые расписания
#

Каждую минуту:

* * * * * command

Каждые 5 минут:

*/5 * * * * command

Каждые 15 минут:

*/15 * * * * command

Каждые 30 минут:

*/30 * * * * command

Каждый час:

0 * * * * command

Каждый день в полночь:

0 0 * * * command

Каждый день в 03:00:

0 3 * * * command

Каждый день в 03:30:

30 3 * * * command

Каждый понедельник в 09:00:

0 9 * * 1 command

По будням в 09:00:

0 9 * * 1-5 command

По выходным:

0 9 * * 6,0 command

Каждого первого числа месяца:

0 0 1 * * command

Каждый день в 08:00, 12:00 и 18:00:

0 8,12,18 * * * command

Каждые 15 минут с 08:00 до 18:59:

*/15 8-18 * * * command

Специальные значения
#

При загрузке системы:

@reboot command

Каждый час:

@hourly command

Каждый день:

@daily command

Каждую неделю:

@weekly command

Каждый месяц:

@monthly command

Каждый год:

@yearly command

Запуск скрипта
#

Допустим, скрипт находится здесь:

/usr/local/bin/backup.sh

Делаем его исполняемым:

chmod +x /usr/local/bin/backup.sh

Запуск каждые 15 минут:

*/15 * * * * /usr/local/bin/backup.sh

Используйте абсолютные пути
#

Через SSH команда может работать:

docker ps

а через cron — нет.

Причина обычно в другом PATH.

Узнать полный путь:

which docker

Например:

/usr/bin/docker

В cron лучше использовать:

*/5 * * * * /usr/bin/docker ps

То же касается команд:

systemctl
ip
curl
rsync
python
docker

PATH в crontab
#

Можно явно указать окружение:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Например:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

*/15 * * * * /usr/local/bin/script.sh

Логи
#

Записать stdout и stderr в файл:

*/15 * * * * /usr/local/bin/script.sh >> /var/log/script.log 2>&1

Где:

>>

добавляет вывод в файл.

А:

2>&1

перенаправляет ошибки туда же.

Отключить вывод
#

Если лог не нужен:

*/15 * * * * /usr/local/bin/script.sh >/dev/null 2>&1

На этапе отладки лучше так не делать.

Логирование через journalctl
#

В скрипте:

logger -t my-script "Script started"

Посмотреть записи:

journalctl -t my-script

Последние 50 записей:

journalctl -t my-script -n 50

Следить в реальном времени:

journalctl -t my-script -f

Пример проверки сервиса
#

Скрипт:

#!/bin/bash

TAG="nginx-check"

if systemctl is-active --quiet nginx; then
    logger -t "$TAG" "nginx is running"
else
    logger -t "$TAG" "nginx is down, restarting"
    systemctl restart nginx
fi

Cron:

*/15 * * * * /usr/local/bin/check-nginx.sh

Логи:

journalctl -t nginx-check

Root crontab
#

Если скрипт выполняет:

systemctl restart ...

или другие действия, требующие root, лучше использовать:

sudo crontab -e

Тогда в самом скрипте sudo обычно не требуется.

Например:

*/15 * * * * /usr/local/sbin/check-service.sh

/etc/crontab
#

crontab -e и /etc/crontab имеют разный формат.

В пользовательском crontab:

*/15 * * * * /usr/local/bin/script.sh

В /etc/crontab присутствует дополнительное поле пользователя:

*/15 * * * * root /usr/local/bin/script.sh

Формат:

минута час день месяц день_недели пользователь команда

Проверка работы cron
#

Статус службы:

systemctl status cron

Запустить:

systemctl start cron

Включить при загрузке:

systemctl enable cron

Или сразу:

systemctl enable --now cron

Логи самого cron
#

Через journalctl:

journalctl -u cron

В реальном времени:

journalctl -u cron -f

На Ubuntu события могут находиться в:

/var/log/syslog

Проверить:

grep CRON /var/log/syslog

Быстрая проверка
#

Добавляем временное задание:

* * * * * date >> /tmp/cron-test.log

Через несколько минут:

cat /tmp/cron-test.log

Если появляются новые строки, cron работает.

После проверки тестовую строку удаляем.

Защита от параллельного запуска
#

Если скрипт запускается каждые 5 минут, но иногда работает 10 минут:

*/5 * * * * /usr/local/bin/backup.sh

может одновременно запуститься несколько экземпляров.

Для защиты используется flock:

*/5 * * * * /usr/bin/flock -n /run/backup.lock /usr/local/bin/backup.sh

Пока один экземпляр работает, следующий запуск будет пропущен.

С логированием:

*/5 * * * * /usr/bin/flock -n /run/backup.lock /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Полезный шаблон crontab
#

Для системного сервера:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""

# Проверка маршрутов каждые 15 минут
*/15 * * * * /usr/bin/flock -n /run/ipsec-routing-check.lock /usr/local/sbin/ipsec-routing-check.sh

# Backup каждый день в 03:00
0 3 * * * /usr/local/bin/backup.sh

# Очистка временных файлов каждое воскресенье в 04:00
0 4 * * 0 /usr/local/bin/cleanup.sh

Что проверить, если cron не работает
#

Проверьте по порядку:

systemctl status cron

Затем:

crontab -l

Или для root:

sudo crontab -l

Запустите скрипт вручную:

/usr/local/bin/script.sh

Проверьте права:

ls -l /usr/local/bin/script.sh

При необходимости:

chmod +x /usr/local/bin/script.sh

Проверьте лог cron:

journalctl -u cron

Проверьте лог самого скрипта:

journalctl -t script-name

Итог
#

cron остаётся одним из самых простых способов автоматизировать периодические задачи в Linux.

Основные команды:

crontab -e

редактирование заданий текущего пользователя.

crontab -l

просмотр заданий.

sudo crontab -e

редактирование заданий root.

Базовый синтаксис:

минута час день_месяца месяц день_недели команда

Например, выполнение скрипта каждые 15 минут:

*/15 * * * * /usr/local/bin/script.sh

Для серверных скриптов желательно:

  • использовать абсолютные пути;
  • писать логи;
  • учитывать ограниченное окружение cron;
  • запускать системные операции из root crontab;
  • использовать flock, если нельзя допускать одновременный запуск нескольких экземпляров.

Для небольших административных задач этого обычно достаточно, чтобы получить простой и надёжный механизм автоматического выполнения команд.

Related

Как изменить образ Docker
·561 слово·3 минут
Основные команды Docker
·1030 слов·5 минут
Простейший HTTP-сервер на Python
·163 слов·1 минута