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

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

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

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

Цель этого сообщества wiki — собрать воедино основные причины, по которым crontabскрипты не выполняются так, как ожидалось. Напишите каждую причину в отдельном ответе.

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

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

решение1

Другая среда

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

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

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

Распространенная "подвох" здесь в том, 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
    

Связанный контент