CronJob не работает

Я установил cronjob для пользователя root в среде Ubuntu следующим образом, набрав crontab -e

  34 11 * * * sh /srv/www/live/CronJobs/daily.sh
  0 08 * * 2 sh /srv/www/live/CronJobs/weekly.sh
  0 08 1 * * sh /srv/www/live/CronJobs/monthly.sh

Но Кронджон не бежит. Я попытался проверить, работает ли cronjob, используя

пгреп крон

и это дает идентификатор процесса 3033. Сценарий оболочки вызывает файл python и используется для отправки электронной почты. Запуск файла Python в порядке. В этом нет ошибки, но cron не запускается. Файл daily.sh содержит следующий код.

python /srv/www/live/CronJobs/daily.py
python /srv/www/live/CronJobs/notification_email.py
python /srv/www/live/CronJobs/log_kpi.py

20 ответов

Решение

WTF?! Мой cronjob не работает?!

Вот контрольный список руководства по отладке не запущенных cronjobs:

  1. Работает ли демон Cron?
    • Бежать ps ax | grep cron и искать хрон.
    • Debian: service cron start или же service cron restart
  2. Cron работает?
    • * * * * * /bin/echo "cron works" >> /tmp/file
    • Синтаксис правильный? Увидеть ниже.
    • Вам, очевидно, нужно иметь доступ на запись к файлу, на который вы перенаправляете вывод. Уникальное имя файла в /tmp который в настоящее время не существует, всегда должен быть доступен для записи.
  3. Команда работает автономно?
    • Проверьте, есть ли в скрипте ошибка, выполнив пробный запуск на CLI
    • при тестировании вашей команды проверьте, что пользователь, чей crontab вы редактируете, может не быть вашим логином или root
  4. Может ли Cron управлять вашей работой?
    • Проверьте /var/log/cron.log или же /var/log/messages за ошибки.
    • Ubuntu: grep CRON /var/log/syslog
    • Красная шляпа: /var/log/cron
  5. Проверьте разрешения
    • установить исполняемый флаг в команде: chmod +x /var/www/app/cron/do-stuff.php
    • если вы перенаправите вывод вашей команды в файл, убедитесь, что у вас есть разрешение на запись в этот файл / каталог
  6. Проверьте пути
    • проверить линию чел-хэнг-бэнгс
    • не полагайтесь на переменные окружения, такие как PATH, поскольку их значение в cron, скорее всего, будет не таким, как в интерактивном сеансе
  7. Не подавлять вывод во время отладки
    • обычно используется это подавление: 30 1 * * * command > /dev/null 2>&1
    • повторно включить стандартный вывод или стандартный вывод сообщения об ошибке

До сих пор не работает? Хлоп!

  1. Поднимите уровень отладки cron
    • Debian
      • в /etc/default/cron
      • задавать EXTRA_OPTS="-L 2"
      • service cron restart
      • tail -f /var/log/syslog чтобы увидеть выполненные сценарии
    • Ubuntu
      • в /etc/rsyslog.d/50-default.conf
      • добавить или закомментировать строку cron.crit /var/log/cron.log
      • перезагрузить регистратор sudo /etc/init.d/rsyslog reload
      • перезапустить cron
      • открыть /var/log/cron.log и искать подробный вывод ошибок
    • Напоминание: отключите уровень журнала, когда вы закончите с отладкой
  2. Запустите cron и снова проверьте файлы журнала

Cronjob Синтаксис

# Minute  Hour  Day of Month      Month         Day of Week    User Command    
# (0-59) (0-23)   (1-31)    (1-12 or Jan-Dec) (0-6 or Sun-Sat)  

    0       2       *             *                *          root /usr/bin/find

Этот синтаксис является правильным только для root пользователь. Обычный пользователь crontab синтаксис не имеет поля User (обычные пользователи не могут запускать код как любой другой пользователь);

# Minute  Hour  Day of Month      Month         Day of Week    Command    
# (0-59) (0-23)   (1-31)    (1-12 or Jan-Dec) (0-6 or Sun-Sat)  

    0       2       *             *                *          /usr/bin/find

Команды Crontab

  1. crontab -l
    • Перечисляет все пользовательские задачи cron.
  2. crontab -e для конкретного пользователя: crontab -e -u agentsmith
    • Запускает сессию редактирования вашего файла crontab.
    • Когда вы выходите из редактора, измененный crontab устанавливается автоматически.
  3. crontab -r
    • Удаляет вашу запись в crontab из спулера cron, но не из файла crontab.

Еще одна причина, по которой crontab потерпит неудачу: специальная обработка % персонаж.

Из файла man:

The entire command portion of the line, up to a newline or a
"%" character, will be executed by /bin/sh or by the shell specified
in the SHELL variable of the cronfile.  A "%" character in the
command, unless escaped with a backslash (\), will be changed into
newline characters, and all data after the first % will be sent to
the command as standard input.

В моем конкретном случае я использовал date --date="7 days ago" "+%Y-%m-%d" произвести параметры для моего сценария, и он молча провалился. Я наконец узнал, что происходит, когда я проверил syslog и увидел, что моя команда была усечена на % условное обозначение. Вы должны избежать этого следующим образом:

date --date="7 days ago" "+\%Y-\%m-\%d"

Смотрите здесь для более подробной информации:

http://www.ducea.com/2008/11/12/using-the-character-in-crontab-entries/

Наконец я нашел решение. Ниже приводится решение:-

  1. Никогда не используйте относительный путь в скриптах Python, выполняемых через crontab. Я сделал что-то вроде этого вместо:-

    import os
    import sys
    import time, datetime
    
    CLASS_PATH = '/srv/www/live/mainapp/classes'
    SETTINGS_PATH = '/srv/www/live/foodtrade'
    sys.path.insert(0, CLASS_PATH)
    sys.path.insert(1,SETTINGS_PATH)
    
    import other_py_files
    
  2. Никогда не подавляйте код crontab, вместо этого используйте mailserver и проверяйте почту для пользователя. Это дает более четкое представление о том, что происходит.

Я хочу добавить 2 пункта, которые я узнал:

  1. Конфигурационные файлы Cron, помещенные в /etc/cron.d/, не должны содержать точку (.). В противном случае он не будет прочитан cron.
  2. Если пользователь, выполняющий вашу команду, не находится в / etc / shadow. Не будет разрешено планировать cron.

Refs:

  1. http://manpages.ubuntu.com/manpages/xenial/en/man8/cron.8.html
  2. https://help.ubuntu.com/community/CronHowto

Чтобы добавить еще одну точку, файл в /etc/cron.d должен содержать в конце пустую новую строку. Вероятно, это связано с ответом Лучано, который указывает, что:

The entire command portion of the line, up to a newline or a "%"
character, will be executed

Это также может быть проблема с часовым поясом.

Cron использует местное время.

Запустите команду timedatectl чтобы увидеть машинное время и убедиться, что ваш crontab находится в том же часовом поясе.

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

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

Вкратце, это означает, что программа, которую вы пытаетесь запустить, пытается отобразить что-то на дисплее X11 (или Wayland и т. Д.) И терпит неудачу, потому что не привязана к графической среде или, фактически, к любому типу средства ввода / вывода. вообще, помимо возможности читать и записывать файлы и отправлять электронную почту, если система настроена таким образом.

Для целей «Я не могу выполнить свою работу», давайте просто обозначим в общих чертах три распространенных сценария этой проблемы. Вероятно, определите случай, который вы пытаетесь реализовать, и выполните поиск связанных вопросов об этом конкретном сценарии, чтобы узнать больше и найти реальные решения с реальным кодом.

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

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

    Внутреннюю службу вполне можно запустить из, хотя, если для ее использования требуется графический интерфейс, можно вместо этого запустить ее из сценариев запуска сервера X11.

  2. Если вы пытаетесь запустить программу с графическим интерфейсом без взаимодействия с реальным пользователем 1 , вы можете настроить «безголовый» сервер X11 2 и запустить задание, которое запускает этот сервер, выполняет ваше задание и завершает работу.

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

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

    Вероятно, ваши сценарии запуска должны просто запускать графический интерфейс (X11 или что-то еще) и подключаться к его сценарию запуска, чтобы также запустить клиентскую программу, как только графический интерфейс будет запущен и запущен. Другими словами, вам здесь не нужно; просто настройте сценарии запуска для запуска графического интерфейса рабочего стола и настройте графический интерфейс рабочего стола для запуска вашего приложения как части (предположительно автоматической, гостевой?) последовательности входа в систему.

Там являются способы для запуска программ Х11 на основном дисплее системы ( DISPLAY=:0.0), но сделать это из задания часто проблематично, поскольку этот дисплей обычно резервируется для реального интерактивного пользователя первым пользователем, который входит в систему и запускает графический рабочий стол. В однопользовательской системе вы можете смириться с последствиями, если этот пользователь также является вами, но это, как правило, имеет неудобные последствия и очень плохо масштабируется.

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

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


1 Распространенным случаем является запуск веб-браузера, который должен запускать полноценный клиент с графическим интерфейсом пользователя, но который управляется программно и которому на самом деле не нужно ничего нигде отображать. Другой - плохо спроектированное научное программное обеспечение, которое не было написано для пакетного использования, и поэтому требует графического интерфейса, даже если вы просто хотите запустить пакетное задание, а затем немедленно выйти без какой-либо реальной необходимости что-либо отображать где-либо.

2 Xvfbявляется стандартным де-факто решением; он запускает «виртуальный кадровый буфер», в котором компьютер может выводить пиксели, как если бы на дисплей, но который на самом деле не подключен к какому-либо дисплейному оборудованию.

Я нашел полезную информацию об отладке на сервере Ubuntu 16.04, выполнив:

systemctl status cron.service

В моем случае мне любезно сообщили, что я оставил комментарий '#' вне строки примечания:

Aug 18 19:12:01 is-feb19 cron[14307]: Error: bad minute; while reading /etc/crontab
Aug 18 19:12:01 is-feb19 cron[14307]: (*system*) ERROR (Syntax error, this crontab file will be ignored)

MTA не установлен, выходные данные отбрасываются

У меня была аналогичная проблема с файлом PHP, выполняемым как задание CRON. Когда я вручную запускаю файл, он работает, но не с вкладкой CRON.

Я получил выходное сообщение: «MTA не установлен, вывод отбрасывается» .

Postfix является агентом передачи почты (MTA) по умолчанию в Ubuntu и может быть установлен с помощью

      sudo apt-get install postfix

Но это же сообщение может быть выведено, когда вы добавляете файл журнала, как показано ниже, и у него нет надлежащего разрешения на запись в /path/to/logfile.log.

      /path/to/php -f /path/to/script.php >> /path/to/logfile.log

Проблема с разрешением может возникнуть, если вы создадите файл cron-log вручную с помощью такой команды, как в то время как вы вошли в систему как другой пользователь, и вы добавляете CRON на вкладке другого пользователя (группы), например с использованием: . Затем демон CRON пытается записать в файл журнала и терпит неудачу, затем пытается отправить вывод в виде электронного письма с помощью MTA Ubuntu, а когда он не найден, выводит «MTA не установлен, вывод отбрасывается».

Чтобы предотвратить это:

  • Создайте файл с надлежащим разрешением.
  • Избегайте создания соответствующего файла журнала CRON вручную, добавьте журнал на вкладке CRON и позвольте файлу журнала создаваться автоматически при запуске cron.

У меня была проблема, похожая на ссылку ниже.

похоже на мою проблему,
мой исходный пост

Моя проблема

Моя проблема заключалась в том, что cron / crontab не выполнял мой сценарий bash. этот сценарий bash выполнил сценарий python.

исходный файл bash

      #!/bin/bash

python /home/frosty/code/test_scripts/test.py

файл python (test.py)

      from datetime import datetime

def main():
    dt_now = datetime.now()
    string_now = dt_now.strftime('%Y-%m-%d %H:%M:%S.%f')
    with open('./text_file.txt', 'a') as f:
        f.write(f'wrote at {string_now}\n')

    return None

if __name__ == '__main__':
    main()

ошибка, которую я получал

        File "/home/frosty/code/test_scripts/test.py", line 7
    string_to_write = f'wrote at {string_now}\n'
                                               ^
SyntaxError: invalid syntax

эта ошибка не имела смысла, потому что код выполнялся без ошибок из файла bash и файла python.

** Примечание -> убедитесь в crontab -eфайл, вы не подавляете вывод. Я отправил результат в файл, добавив >>/path/to/cron/output/file.log 2>&1после команды. ниже моя запись crontab -e

      */5 * * * * /home/frosty/code/test_scripts/echo_message_sh >>/home/frosty/code/test_scripts/cron_out.log 2>&1

проблема

cron использовал неправильный интерпретатор python, вероятно, python 2 из-за синтаксической ошибки.

как я решил проблему

Я изменил свой файл bash на следующий

      #!/bin/bash

conda_shell=/home/frosty/anaconda3/etc/profile.d/conda.sh
conda_env=base

source ${conda_shell}
conda activate ${conda_env}

python /home/frosty/code/test_scripts/test.py

И я изменил свой файл python на следующий

      from datetime import datetime

def main():
    dt_now = datetime.now()
    string_now = dt_now.strftime('%Y-%m-%d %H:%M:%S.%f')
    string_file = '/home/frosty/code/test_scripts/text_file.txt'
    string_to_write = 'wrote at {}\n'.format(string_now)
    with open(string_file, 'a') as f:
        f.write(string_to_write)

    return None

if __name__ == '__main__':
    main()

Ответов уже много, но ни один из них мне не помог, поэтому я добавлю свой сюда на случай, если это будет полезно для кого-то еще.

В моей ситуации мои cronjobs работали, пока не возникла нехватка электроэнергии, которая отключила питание моего Raspberry Pi. Cron поврежден. Я думаю, что именно тогда, когда возникла нехватка, он запускал длинный скрипт Python. Ничего в основном ответе выше у меня не сработало. Однако решение было довольно простым. Мне просто пришлось принудительно переустановить cron с помощью:

      sudo apt-get --reinstall install cron 

Работает сразу после этого.

CRON использует другой TIMEZONE

Очень распространенная проблема: настройки времени cron могут отличаться от ваших. В частности, часовой пояс может быть другим:

      # Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.

Вы можете запустить:

      * * * * * echo $(date) >> /tmp/test.txt

Это должно сгенерировать файл вида:

      # cat test.txt 
Sun 03 Apr 2022 09:02:01 AM UTC
Sun 03 Apr 2022 09:03:01 AM UTC
Sun 03 Apr 2022 09:04:01 AM UTC
Sun 03 Apr 2022 09:05:01 AM UTC
Sun 03 Apr 2022 09:06:01 AM UTC

Если вы используете TZ, отличный от UTC, вы можете попробовать:

      timedatectl set-timezone America/Sao_Paulo

заменять America/Sao_Pauloв соответствии с вашими настройками.

Я не уверен, что это действительно необходимо, но вы можете запустить:

      sudo systemctl restart cron.service

После этого cron работает так, как я и ожидал:

      # cat test.txt 
Sun 03 Apr 2022 09:02:01 AM UTC
Sun 03 Apr 2022 09:03:01 AM UTC
Sun 03 Apr 2022 09:04:01 AM UTC
Sun 03 Apr 2022 09:05:01 AM UTC
Sun 03 Apr 2022 09:06:01 AM UTC
Sun 03 Apr 2022 09:07:01 AM UTC
Sun 03 Apr 2022 09:08:01 AM UTC
Sun 03 Apr 2022 09:09:01 AM UTC
Sun 03 Apr 2022 09:10:01 AM UTC
Sun 03 Apr 2022 06:11:01 AM -03
Sun 03 Apr 2022 06:12:01 AM -03
Sun 03 Apr 2022 06:13:01 AM -03
Sun 03 Apr 2022 06:14:01 AM -03

Я нашел еще одну причину, по которой пользователь не запускает crontab: имя хоста отсутствует в файле hosts:

user@ubuntu:~$ cat /etc/hostname
ubuntu

Теперь файл hosts:

user@ubuntu:~$ cat /etc/hosts
127.0.0.1 localhost

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

Это на Ubuntu 14.04.3 LTS, способ исправить это - добавить имя хоста в файл hosts, чтобы он выглядел примерно так:

user@ubuntu:~$ cat /etc/hosts
127.0.0.1 ubuntu localhost

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

Копирую мой ответ на дублированный вопрос здесь.

cron может не знать, где найти интерпретатор Python, потому что он не использует переменные среды вашей учетной записи.

Для этого есть 3 решения:

  1. Если Python находится в /usr/bin/python, вы можете изменить задание cron, чтобы использовать абсолютный путь: /usr/bin/python /srv/www/live/CronJobs/daily.py

  2. В качестве альтернативы вы также можете добавить значение PATH в crontab с помощью PATH=/usr/bin.

  3. Другое решение - указать интерпретатор в файле сценария, сделать его исполняемым и вызвать сам сценарий в вашем crontab:

    а. Поместите shebang в начало файла python: #!/usr/bin/python.

    б. Установите его в исполняемый файл: $ chmod +x /srv/www/live/CronJobs/daily.py

    c. Поместите это в crontab: /srv/www/live/CronJobs/daily.py

Измените путь к интерпретатору Python, если он отличается в вашей системе.

Ссылка

Для меня решение состояло в том, что файл, который пытался запустить cron, находился в зашифрованном каталоге, точнее, в директории пользователя в /home/. Хотя crontab был настроен как root, так как выполняемый скрипт находился в зашифрованном каталоге пользователя в /home/ cron, он мог читать этот каталог только после того, как пользователь действительно вошел в систему. Чтобы убедиться, что каталог зашифрован, проверьте, существует ли этот каталог:

/home/.ecryptfs/<yourusername>

если так, то у вас есть зашифрованный домашний каталог.

Решением для меня было переместить скрипт в незашифрованный каталог, и все работало нормально.

Пытаться


или

      systemctl start cron

В моем случае я пытался запустить cron локально. Я проверил статус:

      service cron status

Он показал мне:

      * cron is not running

Затем я просто запустил службу:

      service cron start

если вы используете экземпляр ec2(amazon linux), попробуйте проверить журналы в файле /var/spool/mail/[ec2-user]:

nano /var/spool/mail/[ec2-пользователь]

Я столкнулся с той же проблемой, когда crons не работает. Мы исправили, изменив разрешения и владельца Crons сделал root-владельцем, как мы упоминали в crontab AND Cronjobs 644, данное разрешение

Хотя ответ на этот вопрос был принят, я хотел бы добавить, что сработало для меня. рекомендуется указать URL-адрес в кавычках, если он содержит запрос, он может не работать без кавычек.

НЕ ЗАБУДЬТЕ УКАЗАТЬ ВАШ URL, КОТОРЫЙ СОДЕРЖИТ "?, =, #, %" В ЦИТАТУ.

Пример. https://paystack.com/indexphp?docs/api/#transaction-charge-authorization&amp;amp;date=today должен быть в цитате типа "https://paystack.com/indexphp?docs/api/#transaction-charge-authorization&date". =сегодня"

Иногда команда, которую должен выполнить cron, находится в каталоге, к которому у cron нет доступа, как правило, в системах, где разрешения для домашних каталогов пользователей равны 700, а команда находится в этом каталоге.

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