
Часто crontab
сценарии не выполняются по расписанию или не так, как ожидалось. На это есть множество причин:
- неправильная нотация crontab
- проблема с разрешениями
- переменные среды
Цель этого сообщества wiki — собрать воедино основные причины, по которым crontab
скрипты не выполняются так, как ожидалось. Напишите каждую причину в отдельном ответе.
Пожалуйста, укажите одну причину для каждого ответа — подробности о том, почему действие не выполняется, а также исправления, устраняющие эту причину.
Пожалуйста, пишите только о проблемах, специфичных для cron, например, о командах, которые выполняются так, как ожидается от оболочки, но cron выполняет их ошибочно.
решение1
Другая среда
Cron передает минимальный набор переменных окружения в ваши задания. Чтобы увидеть разницу, добавьте фиктивное задание, например:
* * * * * env > /tmp/env.output
Подождите, пока /tmp/env.output
не будет создано, затем снова удалите задание. Теперь сравните содержимое /tmp/env.output
с выводом env
run в вашем обычном терминале.
Распространенная "подвох" здесь в том, PATH
что переменная окружения отличается. Возможно, ваш скрипт cron использует команду, somecommand
найденную в /opt/someApp/bin
, которую вы добавили PATH
в /etc/environment
? cron игнорирует PATH
из этого файла, поэтому запуск somecommand
из вашего скрипта не удастся при запуске с cron, но будет работать при запуске в терминале. Стоит отметить, что переменные из /etc/environment
будут переданы в задания cron, но не те переменные, которые cron специально устанавливает сам, например PATH
.
Чтобы обойти это, просто установите собственную PATH
переменную в верхней части скрипта. Например:
#!/bin/bash
PATH=/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:/bin
15 1 * * * backupscript --incremental /home /root
решение2
Мой главный косяк: Если вы забыли добавить новую строку в конце файла 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)
решение3
Cron daemon не работает. Я действительно облажался с этим несколько месяцев назад.
Тип:
pgrep cron
Если вы не видите номер (т. е. основной PID cron), то cron не запущен. sudo /etc/init.d/cron start
можно использовать для запуска cron.
EDIT: Вместо вызова сценариев инициализации через /etc/init.d используйте служебную утилиту, например
sudo service cron start
EDIT: Также вы можете использовать systemctl в современном Linux, например
sudo systemctl start cron
решение4
Во многих средах cron выполняет команды с использованием sh
, хотя многие предполагают, что он будет использовать bash
.
Предложения по проверке или исправлению ошибки при выполнении команды:
Попробуйте выполнить команду,
sh
чтобы проверить ее работу:sh -c "mycommand"
Оберните команду в подоболочку bash, чтобы убедиться, что она будет запущена в bash:
bash -c "mybashcommand"
Сообщите cron о необходимости запускать все команды в bash, установив оболочку в верхней части вашего crontab:
SHELL=/bin/bash
Если команда представляет собой скрипт, убедитесь, что скрипт содержит шебанг:
#!/bin/bash