Почему скрипты crontab не работают?

Часто, crontab сценарии выполняются не по расписанию или не так, как ожидалось. Для этого есть множество причин:

  1. неправильная запись crontab
  2. проблема с разрешениями
  3. переменные среды

Эта вики-страница сообщества призвана объединить основные причины для crontab сценарии выполняются не так, как ожидалось. Напишите каждую причину в отдельном ответе.

Пожалуйста, укажите одну причину для каждого ответа - подробную информацию о том, почему он не выполняется, - и исправьте (исправьте) по этой единственной причине.

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

Другая среда

Cron передает вашим заданиям минимальный набор переменных среды. Чтобы увидеть разницу, добавьте фиктивное задание, подобное этому:

>* * * * * env /tmp/env.output

Ждать /tmp/env.output будет создано, затем снова удалите задание. Теперь сравните содержимое /tmp/env.output с выходом env запустите в своем обычном терминале.

Распространенной "уловкой" здесь является PATH переменная среды отличается. Возможно, ваш cron-скрипт использует команду somecommand найденный в /opt/someApp/bin, который вы добавили в PATH в /etc/environment? cron игнорирует PATH из этого файла, так что запуск somecommand из вашего скрипта произойдет сбой при запуске с помощью cron, но он будет работать при запуске в терминале. Стоит отметить, что переменные из /etc/environment будут переданы заданиям cron, только не переменные, которые cron специально устанавливает сам, такие как PATH.

Чтобы обойти это, просто установите свой собственный PATH переменная в верхней части скрипта. Например.

#!/bin/bashPATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin# rest of script follows

Некоторые предпочитают вместо этого просто использовать абсолютные пути ко всем командам. Я не рекомендую этого делать. Рассмотрим, что произойдет, если вы захотите запустить свой скрипт в другой системе, и в этой системе команда находится в /opt/someAppv2.2/bin вместо. Вам пришлось бы пройти весь сценарий, заменив /opt/someApp/bin с /opt/someAppv2.2/bin вместо того, чтобы просто сделать небольшую правку в первой строке скрипта.

Вы также можете установить переменную PATH в файле crontab, которая будет применяться ко всем заданиям cron. Например.

PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin15 1 * * * backupscript --incremental /home /root

Мой главный вывод: если вы забудете добавить новую строку в конце crontab файл. Другими словами, файл crontab должен заканчиваться пустой строкой.

Ниже приведен соответствующий раздел на справочных страницах для этой проблемы (man crontab затем переходите к концу):

   Although cron requires that each entry in a crontab end  in  a  newline   character,  neither the crontab command nor the cron daemon will detect   this error. Instead, the crontab will appear to load normally. However,   the  command  will  never  run.  The best choice is to ensure that your   crontab has a blank line at the end.   4th Berkeley Distribution      29 December 1993               CRONTAB(1)

Демон Cron не запущен. Я действительно облажался с этим несколько месяцев назад.

Тип:

pgrep cron 

Если вы не видите числа (т.Е. основного PID cron), значит, cron не запущен. sudo /etc/init.d/cron start может использоваться для запуска cron.

РЕДАКТИРОВАТЬ: Вместо того, чтобы вызывать сценарии инициализации через /etc/init.d, используйте serviceutility, например

sudo service cron start

РЕДАКТИРОВАТЬ: Также вы могли бы использовать systemctl в современном Linux, например

sudo systemctl start cron

Имена файлов скрипта в cron.d/, cron.daily/, cron.hourly/ и т.д., не должны содержать точки (.), в противном случае run-parts пропустит их.

См. Рабочие части(8):

   If neither the --lsbsysinit option nor the --regex option is given then   the names must consist entirely of upper and lower case  letters,  dig‐   its, underscores, and hyphens.   If  the  --lsbsysinit  option  is given, then the names must not end in   .dpkg-old  or .dpkg-dist or .dpkg-new or .dpkg-tmp, and must belong  to   one  or more of the following namespaces: the LANANA-assigned namespace   (^[a-z0-9]+$);   the   LSB   hierarchical   and   reserved   namespaces   (^_?([a-z0-9_.]+-)+[a-z0-9]+$);  and  the  Debian cron script namespace   (^[a-zA-Z0-9_-]+$).

Итак, если у вас есть cron-скрипт backup.sh, analyze-logs.pl в cron.daily/ каталог, вам лучше всего удалить имена расширений.

Во многих средах cron выполняет команды, используя sh, в то время как многие люди предполагают, что он будет использовать bash.

Предложения по тестированию или исправлению этого для неудачной команды:

  • Попробуйте выполнить команду в sh чтобы посмотреть, работает ли это:

    sh -c "mycommand"
  • Оберните команду в подоболочку bash, чтобы убедиться, что она выполняется в bash:

    bash -c "mybashcommand"
  • Скажите cron, чтобы он выполнял все команды в bash, установив оболочку в верхней части вашей crontab:

    SHELL=/bin/bash
  • Если команда является сценарием, убедитесь, что сценарий содержит shebang:

    #!/bin/bash

У меня были некоторые проблемы с часовыми поясами. Cron работал с новым часовым поясом установки. Решение состояло в том, чтобы перезапустить cron:

sudo service cron restart

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

Например, /bin/grep следует использовать вместо grep:

# m h  dom mon dow   command0 0 *  *  *  /bin/grep ERROR /home/adam/run.log &> /tmp/errors

Вместо:

# m h  dom mon dow   command0 0 *  *  *  grep ERROR /home/adam/run.log &> /tmp/errors

Это особенно сложно, потому что одна и та же команда будет работать при выполнении из командной оболочки. Причина в том, что cron не имеет такого же PATH переменная среды в качестве пользователя.

Если ваша команда crontab имеет % символ в нем, cron пытается его интерпретировать. Так что, если вы использовали какую-либо команду с % в нем (например, в спецификации формата для команды date) вам нужно будет экранировать его.

Это и другие хорошие моменты здесь:
http://www.pantz.org/software/cron/croninfo.html

Cron вызывает скрипт, который не является исполняемым.

Запустив chmod +x /path/to/script, скрипт становится исполняемым, и это должно решить эту проблему.

Также возможно, что срок действия пароля пользователя истек. Даже срок действия пароля root может истечь. Ты можешь tail -f /var/log/cron.log и вы увидите сбой cron с истекшим сроком действия пароля. Вы можете установить, чтобы срок действия пароля никогда не истекал, выполнив это: passwd -x -1 <username>

В некоторых системах (Debian, Ubuntu) ведение журнала для cron по умолчанию не включено. В /etc/rsyslog.conf или /etc/rsyslog.d/50-default.conf линия:

# cron.*                          /var/log/cron.log

следует отредактировать (sudo nano /etc/rsyslog.conf) без комментариев к:

cron.*                          /var/log/cron.log

После этого вам необходимо перезапустить rsyslog через

/etc/init.d/rsyslog restart

или

service rsyslog restart 

Источник: Включить ведение журнала crontab в Debian Linux

В некоторых системах (Ubuntu) отдельный файл ведения журнала для cron по умолчанию не включен, но журналы, связанные с cron, отображаются в файле системного журнала. Можно использовать

cat /var/log/syslog | grep cron -i

для просмотра сообщений, связанных с cron.

Вы должны закрыть crontab -e, чтобы cron вступил в силу. Например, используя vim, я редактирую файл и использую :w для его записи, но задание не добавляется в cron, пока я также не завершу работу. Так что я не увижу работу до тех пор, пока я тоже не “:q”.

Я думаю, что лучший способ отладить cron - это проверить системный журнал и найти проблемы.

В моем случае - электронное письмо направлялось в мою папку со спамом, так что … проверьте это, прежде чем тратить часы на отладку :smiley:

Пожалуйста, проверьте это cron - Script doesn't run via crontab but works fine standalone - Ask Ubuntu

Перебои с электричеством