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

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

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

Целью этой вики-сообщества является агрегирование. основные причины того, что сценарии crontab не были выполнены должным образом. Запишите каждую причину в отдельном ответе.

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

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

604
задан 8 May 2017 в 21:15

46 ответов

Другая среда

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/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
563
ответ дан 8 May 2017 в 21:15

На основе того, что Aaron Пирт упомянул о подробном режиме, иногда скрипты, не находящиеся в подробном режиме, инициализируются, но не завершаются, если по умолчанию включенная команда выводит на экран одну или несколько строк после запуска процедуры. Например, я написал сценарий резервного копирования для нашей интрасети, который использовал curl, утилиту, которая загружает или выгружает файлы на удаленные серверы, и очень удобен, если вы можете получить доступ к указанным удаленным файлам только через HTTP. Использование 'curl http://something.com/somefile.xls ' приводило к зависанию написанного мной сценария и никогда не завершению, потому что он выплевывал новую строку, за которой следовала строка выполнения. Мне пришлось использовать флаг (-ы) молчания, чтобы указать ему не выводить какую-либо информацию, и написать свой собственный код для обработки, если файл не удалось загрузить.

2
ответ дан 8 May 2017 в 21:15

Хотя вы можете определять переменные среды в своем crontable, вы не работаете в сценарии оболочки. Таким образом, конструкции, подобные приведенной ниже, работать не будут:

SOME_DIR=/var/log
MY_LOG_FILE=${SOME_LOG}/some_file.log

BIN_DIR=/usr/local/bin
MY_EXE=${BIN_DIR}/some_executable_file

0 10 * * * ${MY_EXE} some_param >> ${MY_LOG_FILE}

Это потому, что переменные не интерпретируются в crontable: все значения берутся буквально. И это то же самое, если вы опустите скобки. Таким образом, ваши команды не будут выполняться, и ваши файлы журналов не будут записаны ...

Вместо этого вы должны определить все переменные среды прямо:

SOME_DIR=/var/log
MY_LOG_FILE=/var/log/some_file.log

BIN_DIR=/usr/local/bin
MY_EXE=/usr/local/bin/some_executable_file

0 10 * * * ${MY_EXE} some_param >> ${MY_LOG_FILE}
2
ответ дан 8 May 2017 в 21:15

Когда задача выполняется в cron, stdin закрывается. Программы, которые действуют по-разному в зависимости от того, доступен ли stdin или нет, будут вести себя по-разному в сеансе оболочки и в cron.

Примером является программа goaccess для анализа файлов журналов веб-сервера. Это НЕ работает в cron:

goaccess -a -f /var/log/nginx/access.log > output.html

и goaccess показывает страницу справки вместо создания отчета. В оболочке это можно воспроизвести с помощью

goaccess -a -f /var/log/nginx/access.log > output.html < /dev/null

. Исправление для goaccess состоит в том, чтобы заставить его читать журнал из стандартного ввода, а не из файла, поэтому решение состоит в том, чтобы изменить запись crontab на

cat /var/log/nginx/access.log | goaccess -a > output.html
2
ответ дан 8 May 2017 в 21:15

На моих серверах RHEL7 запускались задания root cron, а задания пользователей - нет. Я обнаружил, что без домашнего каталога задания не будут выполняться (но вы увидите хорошие ошибки в / var / log / cron). Когда я создал домашний каталог, проблема была решена.

0
ответ дан 8 May 2017 в 21:15

У меня была проблема со скриптом, который вызывал grep с регулярным выражением. Некоторые регулярные выражения работали, когда скрипт вызывался из crontab, а другие - нет, например [[: print:]] не работает. Оказывается, переменная окружения LANG влияет на наборы символов, такие как [a-z] или [[: print:]]. Когда я вставил переменную среды LANG в верхнюю часть моего crontab, то есть «LANG = en_GB.UTF-8», все регулярные выражения grep работали нормально, когда скрипт вызывался из crontab. НТН.

0
ответ дан 8 May 2017 в 21:15

Если вы отредактировали файл crontab, используя редактор окон (через samba или что-то еще), и он заменил символы новой строки на \ n \ r или просто \ r, cron не запустится.

Кроме того, если вы используете /etc/cron.d/* и в одном из этих файлов есть \ r, cron будет перемещаться по файлам и останавливаться, когда попадет в плохой файл. Не уверен, что это проблема?

Использование:

od -c /etc/cron.d/* | grep \r
0
ответ дан 8 May 2017 в 21:15

В 16.04, если у вас есть эта ошибка в системном журнале

(CRON) error (can't fork)

, попробуйте:

systemctl status cron.service

В результате:

Tasks: num_task (limit: 512)

If num_task близок к пределу использования:

systemctl set-property cron.service TasksMax=new_max

Замените new_max подходящим значением.

0
ответ дан 8 May 2017 в 21:15

Если crontab упоминает что-то вроде run-parts /etc/cron.daily, то run-parts может отказываться запускать ваш скрипт , В моем случае сценарий в cron.daily не начинался с #! / Bin / sh .

Я обнаружил это, поместив свой скрипт в каталог и запустив run-parts для этого каталога.

0
ответ дан 8 May 2017 в 21:15

Стандартные файлы .bashrc в UBuntu 16.04 (и многих других версиях) имеют встроенный механизм, который ничего не делает , если они не являются интерактивной оболочкой.

Это может помешать правильному источнику файла в скрипте, запущенном cron! Чтобы предотвратить это, закомментируйте следующие строки в верхней части вашего файла .bashrc:

Ubuntu 16.04

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Ubuntu 12.04 и некоторые другие версии

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Пока они остаются, если cron запускает скрипт, который получает ваш файл .bashrc, вы на самом деле не получите никаких переменных окружения, к которым вы привыкли, внутри вашего терминала! [ 117]

0
ответ дан 8 May 2017 в 21:15

Запись в cron через "crontab -e" с аргументом имени пользователя в строке. Я видел примеры, когда пользователи (или системные администраторы) писали свои сценарии оболочки и не понимали, почему они не автоматизируют. Аргумент «пользователь» существует в / etc / crontab, но не в пользовательских файлах. так, например, ваш личный файл будет выглядеть примерно так:

# m h dom mon dow command

* * */2  *   *  /some/shell/script

, тогда как / etc / crontab будет:

# m h dom mon dow user   command

* * */2  *   *  jdoe   /some/shell/script

Итак, зачем вам последний вариант? Что ж, в зависимости от того, как вы хотите установить свои разрешения, это может стать очень запутанным. Я написал сценарии для автоматизации задач для пользователей, которые не понимают тонкостей или не хотят возиться с рутинной работой. Установив разрешения на - x ------ , я могу сделать скрипт исполняемым, чтобы они не могли его прочитать (и, возможно, случайно изменить). Однако я мог бы захотеть запустить эту команду с несколькими другими из одного файла (что упростило бы обслуживание), но убедитесь, что для вывода файла назначен правильный владелец. Это (по крайней мере, в Ubuntu 10.10) ломается как из-за невозможности прочитать файл, так и из-за его выполнения, а также из-за вышеупомянутой проблемы с помещением точек в / etc / crontab (что, как ни странно, не вызывает ошибок при прохождении crontab -e ).

В качестве примера я видел экземпляры sudo crontab -e , используемые для запуска сценария с правами root, с соответствующим именем пользователя chown file_output в сценарии оболочки. Коряво, но работает. IMHO, более изящный вариант - поместить его в / etc / crontab с объявленным именем пользователя и соответствующими разрешениями, чтобы file_output попал в нужное место и к нужному владельцу.

2
ответ дан 8 May 2017 в 21:15

Это недавно произошло со мной: у меня было две строки, которые изменили PATH, например:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/home/ernesto/bin

Затем, позже в файле:

PATH=$PATH:/some/other/path

, как один обычно делают в интерпретируемом оболочкой контексте. Тем не менее, $ PATH, похоже, не был расширен, что привело к сбою всех моих заданий. Решение состоит в том, чтобы поместить все в одну строку.

Редактировать:

Так как я не хотел ждать, пока следующая нормальная итерация anacron, чтобы проверить, правильно ли работают мои работы, я запустил:

anacron -fnd "jobname"

Где «имя работы» идентификатор задания, указанный в anacrontab. Это заставляет задания выполняться одним и тем же анакронным процессом последовательно и без задержки.

0
ответ дан 8 May 2017 в 21:15

Разрешения на ведение журнала

Очень простой кронтаб, не будет выполнен, потому что /var/log/ не записывается учетной записью luser!

* * * * * /usr/local/bin/teamviewer_check >> /var/log/teamviewer.log 2>&1

РЕШЕНИЕ: создайте файл в качестве корневого и chmod на 777

Благодаря предыдущему предложению включить регистрацию cron в /etc/rsyslog.d/50-default.conf, это приведет к записи syslog (MTA не установлено, вывод отбрасывается), а затем благодаря "(CRON) info (Ошибка "No MTA installed, disarding output)" в syslog при установке постфикса в локальном режиме, tail /var/mail/luser, /bin/sh: 1: не может создать /var/log/teamviewer.log: Разрешение запрещено

2
ответ дан 8 May 2017 в 21:15

Задания Cron не будут выполняться, если срок действия пароля вашего пользователя истек.

Одним из свидетельств этого является наличие журнала cron (обычно / var / log / syslog в Ubuntu, I считают), содержит сообщения типа «Маркер аутентификации больше не действителен; требуется новый».

Вы можете проверить наличие этой проблемы, запустив sudo chage -l the_username .

Вот пример просроченного пароль:

$ sudo chage -l root
Last password change                    : password must be changed
Password expires                    : password must be changed
Password inactive                   : password must be changed
Account expires                     : never
Minimum number of days between password change      : 0
Maximum number of days between password change      : 14600
Number of days of warning before password expires   : 14

Исправление заключается в изменении пароля. Например:

sudo -u root passwd

Затем следуйте инструкциям, указав новый пароль по запросу.

Спасибо https://serverfault.com/questions/449651/why-is-my-crontab-not-working- and-how-can-i-Troubleshoot-it # comment966708_544905 за то, что указали мне правильное направление. В моем случае, как и в случае с этим комментатором, это был пользователь root в ящике DigitalOcean.

2
ответ дан 8 May 2017 в 21:15

Через несколько часов выяснилась проблема, когда я редактировал скрипт оболочки из Windows ( notepad ++ ), где файл изначально находился на сервере Linux, и я пропустил символ новой строки.

Так как я использовал Notepad ++ для редактирования файла, мне пришлось выполнить преобразование EOL в Unix , чтобы получить символ новой строки, и это сработало отлично.

Надеюсь, это поможет!

0
ответ дан 8 May 2017 в 21:15

Однажды я работал на общем сервере с множеством ограничений .

Все ответы здесь (PATH, SHELL, bash -c, ...) не могли заставить мой скрипт работать в crontab.

Это сработало идеально, когда я поместил команду в небольшой файл сценария с PATH, SHELL и shebang, а не в сам crontab. Мне пришлось изменить разрешения на 700.

0
ответ дан 8 May 2017 в 21:15

Другой протест:

Попытка не поместить Ваши сценарии крона в корневой каталог пользователя.

у меня просто была проблема, где все казалось хорошим, но сразу после некоторое время - вероятно, спустя несколько часов после того, как я выхожу из системы, задания крона прекращают работать, и эти сообщения появляются в журнале:

Signature not found in user keyring
Perhaps try the interactive 'ecryptfs-mount-private'

Мой корневой каталог, по крайней мере, насколько я знаю, не шифруется. Но тем не менее, перемещение тех сценариев за пределами домашнего dir решило проблему.

1
ответ дан 8 May 2017 в 21:15

Мой crontab работал только когда я вошел как пользователь.

Я нашел решение, предложенное здесь на Unix & amp; Linux SE

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

Я исправил проблему, поместив свои скрипты в папку /usr/local/bin.

0
ответ дан 8 May 2017 в 21:15

Если вы запускаете скрипты в каталогах /etc/cron.*, убедитесь, что ваши скрипты:

  • исполняемы,
  • соответствуют пространству имен скриптов cron Ubuntu / Debian (^[a-zA-Z0-9_-]+$).

Так, например, если у вас есть скрипт с расширением (например, .sh), он не будет работать.

Чтобы напечатать названия сценариев, которые будут запускаться ежечасно, попробуйте:

sudo run-parts --report --test /etc/cron.hourly
0
ответ дан 8 May 2017 в 21:15

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

В таких случаях я считаю полезным заключить цель в другой короткий скрипт, который выводит некоторый видимый код отладки (включая вывод date) и использует перенаправление, чтобы убедиться, что я получаю некоторые доказательства для проверки. Если целью является сценарий, обтекание sh -x может помочь в дальнейшем.

Запись в crontab (всегда редактируемая с помощью crontab -e) может выглядеть так:

00 14 * * * (sh -x /tmp/my_wrapper_script) >> /tmp/debug.log 2>&1

Проверять /tmp/debug.log и его метку времени. Если он пустой, не существует или временный усилитель не вскоре после 14:00 (в этом примере), у вас может быть проблема cron, в противном случае вам нужно отладить фактическое целевое действие, и cron работает просто отлично!

0
ответ дан 8 May 2017 в 21:15

У меня были некоторые проблемы с использованием sudo в cron.

По сути, я хотел запустить команду от имени конкретного пользователя, и я сначала проверил в командной строке su, что вернуло ошибку This account is not available. Используя sudo, команда была выполнена без ошибок.

Однако при запуске из cron команда sudo вернула следующую ошибку: sudo: sorry, you must have a tty to run sudo.

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

0
ответ дан 8 May 2017 в 21:15

Еще одно замечание:

Когда вы наберете crontab -e и сохраните в редакторе, это не будет иметь никакого эффекта. Вы должны выйти из редактора, чтобы добавить или обновить его в соответствии с вашими изменениями (например, используйте :x в Vim).

(crontab -e эффективно запускает «редактировать файл cron; обновлять из файла cron», поэтому он блокируется в редакторе, пока вы его не закроете.)

0
ответ дан 8 May 2017 в 21:15

Вы использовали:

*  *  * * * DISPLAY=:0 /path/to/your/app

, но это не удалось, потому что ваш каталог ~/.dbus принадлежит не вам, а root. Проверьте это:

ls -l ~/.dbus
0
ответ дан 8 May 2017 в 21:15

Демон Cron может работать, но на самом деле не работает. Попробуйте перезапустить cron:

sudo /etc/init.d/cron restart
2
ответ дан 8 May 2017 в 21:15

Моя главная проблема: если вы забыли добавить новую строку в конец файла 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)
375
ответ дан 8 May 2017 в 21:15

Я писал скрипт инсталляционного командного интерпретатора, который создает другой скрипт для очистки данных старых транзакций от базы данных. Как часть задачи он должен был настроить ежедневную работу cron для запуска в произвольное время, когда нагрузка на БД была низкой. Я создал файл mycronjob с cron расписанием, именем пользователя и командой и скопировал его в /etc/cron.каталог d. Две мои догадки:

  1. mycronjob файл должен был принадлежать root, чтобы запустить
  2. Я должен был установить права доступа к файлу в 644 - 664 не будет запущен.

Проблема с разрешениями появится в /var/log/syslog как нечто подобное:

Apr 24 18:30:01 ip-11-22-33-44 cron[40980]: (*system*) INSECURE MODE (group/other writable) (/etc/crontab)
Apr 24 18:30:01 ip-11-22-33-44 cron[40980]: (*system*) INSECURE MODE (group/other writable) (/etc/cron.d/user)

Первая строка относится к файлу /etc/crontab, а вторая - к файлу, который я поместил под /etc/cront. d.

3
ответ дан 8 May 2017 в 21:15

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

Тип:

pgrep cron 

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

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

sudo service cron start

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

sudo systemctl start cron
157
ответ дан 8 May 2017 в 21:15

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

См. 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 , analysis-logs.pl в каталоге cron.daily / ,лучше всего удалить имена расширений.

100
ответ дан 8 May 2017 в 21:15

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

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

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

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

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

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

     #! / Bin / bash
     
77
ответ дан 8 May 2017 в 21:15

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

sudo service cron restart
45
ответ дан 8 May 2017 в 21:15

Другие вопросы по тегам:

Похожие вопросы: