вторник, 25 июля 2017 г.

Некоторые общие проблемы с cron

Наиболее популярным планировщиком заданий в Linux является демон cron.
Демон сервиса под названием crond читает файлы конфигураций (/etc/crontab, /etc/cron.*, /var/spool/cron) и выполняет запланированные задания.

Существуют особенности работы с cron и некоторые сталкиваются с трудностями при его использовании.

1. Можно легко удалить файл crontab просто опечатавшить на одну клавишу
Команда crontab -e используется для редактирования файла /etc/crontab, а команда crontab -r очищает этот файл, поэтому можно случайно получить пустой файл.
Если crontab давно не редактировался и в нем находилось небольшое количество записей, то восстановить его можно по логам (/var/log/cron.log, /var/log/syslog):
$ grep CRON /var/log/syslog
Jul  7 13:17:01 localhost CRON[26085]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)
Jul  7 14:17:01 localhost CRON[29191]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)
Jul  7 15:17:01 localhost CRON[1477]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)

По этому логу можно увидеть, что задание:
cd / && run-parts --report /etc/cron.hourly
запускается каждый час в 17 минут.
Поэтому восстановленная запись выглядела скорее всего вот так:
17 * * * * root cd / && run-parts --report /etc/cron.hourly

2. Cron не понимает системный PATH
Такая запись:
$ crontab -e
* * * * * ls -l
не сработает, так как cron не может найти команду ls.

В таком случае необходимо в файле crontab прописать PATH:
$ crontab -e
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
* * * * * ls -l

Или же прописывать полный путь к исполняемому файлу, например:
$ crontab -e
* * * * * /bin/ls -l

3. Минимальный интервал срабатывания задания - 1 минута
Если нужно запускать задание чаще чем одна минута, то приходится использовать некоторые ухищрения.

Пример того как можно запускать задание раз в 20 секунд:
$ cat /etc/cron.d/hello.sh
#!/bin/sh
echo Hello 1st time
sleep 20
echo Hello 2nd time
sleep 20
echo Hello 3rd time

Запись в crontab будет выглядеть так:
$ crontab -e
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
* * * * * sh /etc/cron.d/hello.sh

4. Иногда возникает путаница с указанием пользователя
В случае использования файла /etc/crontab или файлов в /etc/cron.* необходимо указывать имя пользователя, например:
# cat /etc/crontab
* * * * * apache /bin/ls -l
тут указывается пользователь apache, из-под которого будет запущено задание.

При запуске команды crontab -e из-под пользователя указывать имя пользователя не нужно, оно будет автоматически запущено под именем этого пользователя:
$ crontab -u username -e
* * * * * /bin/ls -l

5. Если в конце файла crontab нет пустой строки, то он не сработает
Выдержка из man crontab гласит:
cron requires that each entry in a crontab end in a newline character. If the last entry in a crontab is missing the newline, cron will consider the crontab (at least partially) broken and refuse to install it.

Вот такой-вот странный баг.

6. Всегда указывайте интерпретатор при запуске скрипта или назначайте правильные права
Вот такая запись в crontab может не сработать:
$ crontab -e
* * * * * /etc/cron.d/hello.sh
если файл не имеет соответствующих прав (например принадлежит другому пользователю) или не установлен бит исполнения файла.

Проверить владельца файла можно командой stat или ls -l.
Вторая команда также может показать установлен ли бит исполнения для скрипта или нет:
$ ls -l /etc/cron.d/hello.sh
-rw-r--r-- 1 user1 user1 964 jul  6 16:41 /etc/cron.d/hello.sh

7. Если скрипты запуска, расположенные в каталогах /etc/cron.{daily,hourly,monthly,weekly} имеют в своем имени точку, то они игнорируются
Именно из-за этого стоит придерживаться практики разделять имена скриптов дефисом:
$ ls /etc/cron.daily/
0anacron    aptitude      cracklib-runtime  google-chrome  logrotate  mlocate        passwd  slack
apt-compat  bsdmainutils  dpkg              libvirt-bin    man-db     opera-browser  samba   update-notifier-common

8. Символ "%" используется для обозначения новой строки в командах cron
Для того чтобы использовать этот символ в скриптах, то его нужно экранировать "\%".
Пример:
$ crontab -e
* * * * * /bin/date +\%Y-\%m-\%d

Знание таких особенностей работы cron позволит немного сократить время решения возникающих с ним проблем.

Комментариев нет: