Linux: cron, crontab, at, atd

Общее

  • В docker image может отсутствовать cron и даже редактор для управления
apt install cron
apt install vim
  • Про at, atd подробнее в конце статьи отдельный раздел (включая список литература), в целом статья про cron
  • Крутой мануал на русском по настройке CronTab, большая часть ин-ии оттуда
  • Wiki помимо теории есть пример настройки
  • Даже приложения типа cacti используют cron для своей работы (переодический запуск опросчика и рисователя)
Из установки Cacti:
9) Создаём задание в кроне
crontab -e
*/5 * * * * php /var/www/cacti/poller.php > /dev/null 2>&1

cron — демон-планировщик задач в UNIX-подобных операционных системах, использующийся для периодического выполнения заданий в определённое время. Регулярные действия описываются инструкциями, помещенными в файлы crontab.

Предположим нам нужно запускать определенную задачу каждый день, или, может, каждую субботу в 12 ночи? В Unix-подобных системах существует возможность автоматизировать запуск повторяющихся задач при помощи демона планировщика задач cron.

Ключи

Для управления планировщиком задач обычно используется команда crontab со следующими ключами:

    • crontab -l – показывает список текущих задач.
    • crontab -e – запускает редактор планировщика задач для редактирования файла crontab вашего пользователя. Тут можно создавать задания. Редактор берется из переменной EDITOR, я предпочитаю для crontab VIM, поэтому даже на системах где EDITOR выставлен другой, перед crontab -e устанавливаю его в VIM через export EDITOR=vim. Нужно учесть, что запись файла через команду w без выхода wq из режима редактирования не приведет к установке нового crontab, установка происходит только после выхода из файла.
    • crontab -r – удаляет все текущие задачи.
    • crontab -u <username> – определяет пользователя, чьи задачи будут просматриваться/редактироваться, отсутствие данного параметра устанавливает текущего пользователя.
[root@localhost ~]# sudo crontab -u user3 -l
no crontab for user3
[root@localhost ~]# sudo crontab -u user3 -e

Таким образом, для назначения определенной задачи нужно выполнить команду crontab -e и построчно написать список необходимых задач на основе синтаксиса cron.

В некоторых случаях crontab отсутсвует в системе, но при этом сам cron вполне себе присутствует. Управление в таком случае может осуществляться напрямую в пользовательских файлах без использования crontab, напр. по пути:

/var/spool/cron/crontabs/root  # for root
/var/spool/cron/crontabs/user  # for user

Синтаксис

    • https://crontab.guru/ – Очень удобный сайт с примерами и возможностью подбора синтаксиса

В общем виде задача крон представляет собой строку вида:

* * * * * команда

Каждой звездочке в строке соответствует определенное значение:

*                  *             *                *              *                        команда
Минута (0-59)     Час (0-23)    День (1-31)     Месяц (1-12)    День недели (0-7)      Строка выполняемой команды

0 и 7 в дне недели обозначает воскресенье, поскольку в некоторых странах день недели начинается с воскресенья. Соответственно 1 – понедельник, 6 – суббота. В файле crontab помимо перечисленных выше допустимы следующие основные символы:

# - комментарий  (строки, начинающиеся с данного символа, не выполняются);
, - перечисление значений (1,2,3,4);
*/ - каждые n раз (*/n - каждые n, */5 - каждые 5, */2 - каждые 2);
- - интервал значений (1-5 - с 1 до 5, 4-6 - с 4 до 6).

Примеры настройки расписания

    • https://crontab.guru/ – Очень удобный сайт с примерами и возможностью подбора синтаксиса

Из вышеперечисленного следует, что следующие записи соответствуют следующим строкам:

МИНУТЫ
*/10 * * * * /home/www/myscript.php - каждые 10 минут;
24 * * * * /home/redkin/bin/script.sh - запускаемся каждую 24 минуту нового часа, полезно при тестах - ставишь на минуту-две позже текущего времени и смотришь отработку.

ДНИ
0 5 * * * /usr/bin/certbot renew --quiet - каждый день в 5:00 запускаем обновление TLS сертификата используя certbot
0 1 */1 * * /home/redkin/bin/exp_backup_daily_cacti – каждый день в 01:00
5 4 */7 * * /home/www/myscript.php - запуск задания каждые 7 дней в 4:05.

ДНИ НЕДЕЛИ
5 4 * * 1 /home/www/myscript.php - каждый понедельник в 4:05.
0 9 * * 1,3,5 /home/www/myscript.php - понедельник, среду и пятницу в 9 утра;
45 6 * * 1-5 /home/user/beep.sh - в 6:45 каждый рабочий день
0 18 * * 1-5 echo "Приезжай домой, Хозяин" | mail -s "Конец рабочего дня" user  - в конце каждого рабочего дня отсылается сообщение о том, что пора домой

МЕСЯЦЫ
0 2 1 * * /home/www/myscript.php - каждое 1-е число месяца в 02:00

ГОДЫ
0 2 1 1 * /home/www/myscript.php - 1 января каждого года в 02:00

Так же в файле crontab можно записывать следующие предопределенные значения:

@reboot - приветствие при каждой загрузке системы;
         @reboot echo 'Привет, Хозяин!'
@yearly - каждый год в полночь 1-го января;
         @yearly echo 'С Новым годом' - поздравление с новым годом каждый год в полночь 1-го января;
@monthly - каждый месяц в полночь 1-го числа;
@weekly - в полночь каждый понедельник;
@daily - ежедневно в 0:00;
         0 0 */1 * * /home/redkin/bin/exp_backup_daily_cacti
@hourly - в начале каждого часа.
         0 */1 * * * /home/redkin/bin/exp_backup_daily_cacti

Настройки системы

Стандартные настройки Cron включают объявление переменных. Это нужно для множества вещей – например установки кодировки, определения пути к файлу tnsnames.ora для Oracle или просто чтобы не ругался на ошибки неполного пути (самая частая ошибка когда скрипт из консоли запускается, но по cron нет, в противном случае нужно путь для многих утилит искать через whereis), отсылал все ошибки на твою почту, а не на учетную запись типа <user>@domain (очень полезно).

SHELL=/bin/bash 
PATH=/home/redkin/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
HOME=/home/redkin
MAILTO="petr@redkin.net"
LC_CTYPE=en_US.UTF-8

В противном случае в syslog (мы пробовали отправить письмо, но mail-сервер выдает ошибки т.к. такого пользователя нет):

Sep 24 23:30:02 server sSMTP[15981]: RCPT TO:<cacti@corbina.ru> (550 cacti@corbina.ru unknown user account)

Так же может понадобиться объявление дополнительных переменных, например, для работы Oracle-клиента.

LD_LIBRARY_PATH=/usr/lib/oracle/12.1/client64/lib:$LD_LIBRARY_PATH
NLS_LANG=RUSSIAN_CIS.UTF8

В случае если для какого-то скрипта нужно эти переменные будет поменять прописываем это в строчке со скриптом

NLS_LANG=RUSSIAN_CIS.CL8MSWIN1251; /home/redkin_p/bin/check_tt.rb

Ошибки

Если cron не работает – в первую очередь проверяем включен ли сервис (в зависимости от ОС):

service cron status
service crond status
systemctl status cron

Пример:
# service cron status
[FAIL] cron is not running ... failed!

Включаем и добавляем автозапуск:

service cron start
systemctl enable cron
update-rc.d cron defaults

# service cron start
[ ok ] Starting periodic command scheduler: cron.
root@35c4810c1e60:/var/www/html#
# service cron status
[ ok ] cron is running.

Логи запуска/отработки скриптов по крону хранятся в (так же зависит от ОС):

/var/log/syslog
/var/log/cron.log

Логи ошибок скриптов по крону по умолчанию приходят на почту локального пользователя (лучше задать конкретную почту – см. выше), но можно редиректить по стандарту все логи при запуске скрипта в отдельный файл. Я так делал, например, когда логи ошибок очень большие , по каким то причинам регулярные (привет, cacti!), на почте нет желания их хранить, но и в /dev/null не хочется их дропать.

0 0 */1 * * /home/redkin/bin/exp_backup_daily_cacti &>/home/redkin/log
24 * * * * /home/redkin/bin/script.sh - запускаемся каждую 24 минуту нового часа, полезно при тестах - ставишь на минуту-две позже текущего времени и смотришь отработку.

Если выдает ошибку Jan 28 12:25:01 server cron[24090]: Неизвестный модуль, то может помочь простой рестарт cron. Особенно если это после обновления. Обычно в качестве имени нужно указать cron или crond, в gentoo делается через vixie-cron.

sudo /etc/init.d/cron restart
sudo /etc/init.d/crond restart
sudo /etc/init.d/vixie-cron restart

 

AT/ATD

manual

install

apt install at
service atd status

use

# at 20:24 -f /root/test.sh # run
    warning: commands will be executed using /bin/sh
    job 1 at Thu Jan 28 20:24:00 2021

# at -c 1 # info about job

Leave a Reply