Как смоделировать среду, с которой cron выполняет скрипт? - PullRequest
239 голосов
/ 25 января 2010

У меня обычно есть несколько проблем с тем, как cron выполняет скрипты, так как они обычно не имеют моей настройки среды. Есть ли способ вызвать bash (?) Таким же образом, как это делает cron, чтобы я мог тестировать сценарии перед их установкой?

Ответы [ 12 ]

366 голосов
/ 30 марта 2010

Добавьте это в свой cron:

30 08 * * * env > ~/cronenv

После запуска сделайте следующее:

env - `cat ~/cronenv` /bin/sh

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

61 голосов
/ 26 января 2010

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

  • HOME домашний каталог пользователя
  • LOGNAME логин пользователя
  • PATH=/usr/bin:/usr/sbin
  • SHELL=/usr/bin/sh

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

45 голосов
/ 27 марта 2014

Пара подходов:

  1. Экспорт cron env и источник его:

    Добавить

    * * * * * env > ~/cronenv
    

    в ваш crontab, дайте ему один раз поработать, выключите его и запустите

    env - `cat ~/cronenv` /bin/sh
    

    И теперь вы находитесь в sh сеансе с окружением cron

  2. Перенеси свою среду в cron

    Вы можете пропустить вышеупомянутое упражнение и просто сделать . ~/.profile перед своей работой cron, например,

    * * * * * . ~/.profile; your_command
    
  3. Использование экрана

    Выше двух решений все еще не удается, поскольку они предоставляют среду, подключенную к запущенному сеансу X, с доступом к dbus и т. Д. Например, в Ubuntu nmcli (Network Manager) будет работать в двух вышеуказанных подходах, но все еще терпят неудачу в cron.

    * * * * * /usr/bin/screen -dm
    

    Добавьте указанную выше строку в cron, дайте ей поработать один раз, выключите ее. Подключитесь к экранной сессии (screen -r). Если вы проверяете, что сеанс экрана был создан (с ps), имейте в виду, что они иногда находятся в столицах (например, ps | grep SCREEN)

    Теперь даже nmcli и аналогичные сбои.

21 голосов
/ 26 января 2010

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

env - your_command arguments

Это запустит your_command с пустым окружением.

14 голосов
/ 05 марта 2011

В зависимости от оболочки аккаунта

sudo su
env -i /bin/sh

или

sudo su
env -i /bin/bash --noprofile --norc

С http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html

12 голосов
/ 19 сентября 2016

Отвечая шесть лет спустя: проблема несоответствия среды является одной из проблем, решаемых systemd «таймерами» в качестве замены хрон. Независимо от того, запускаете ли вы «service» systemd из CLI или через cron, он получает точно такую ​​же среду, избегая проблемы несоответствия среды.

Наиболее распространенная проблема, приводящая к сбою заданий cron при их ручном прохождении, - это ограничение по умолчанию $PATH, устанавливаемое cron, например в Ubuntu 16.04:

"/usr/bin:/bin"

В отличие от этого, по умолчанию $PATH, установленное systemd в Ubuntu 16.04:

"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

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

Недостаток системных таймеров, это немного больше времени для их установки. Сначала вы создаете файл «service», чтобы определить, что вы хотите запустить, и файл «timer», чтобы определить расписание его запуска и, наконец, «включить» таймер, чтобы активировать его.

10 голосов
/ 26 января 2010

Создать задание cron, которое запускает env и перенаправляет stdout в файл. Используйте файл вместе с «env -», чтобы создать ту же среду, что и задание cron.

3 голосов
/ 26 января 2010

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

http://libslack.org/daemon/

2 голосов
/ 26 января 2010

По умолчанию cron выполняет свои задания, используя представление вашей системы о sh. Это может быть реальная оболочка Bourne или dash, ash, ksh или bash (или другой), которые связаны с sh (и, как следствие, работают в режиме POSIX).

Лучше всего убедиться, что в ваших скриптах есть то, что им нужно, и предположить, что для них ничего не предусмотрено. Следовательно, вы должны использовать полные спецификации каталогов и устанавливать переменные среды, такие как $PATH самостоятельно.

1 голос
/ 12 июня 2014

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

Редактирование скрипта /etc/cron.d/:

* * * * * user1 comand-that-needs-env-vars

Превратится в:

* * * * * user1 source ~/.bash_profile; source ~/.bashrc; comand-that-needs-env-vars

Грязно, но это сделало работу за меня. Есть ли способ симулировать логин? Просто команда, которую вы могли бы запустить? bash --login не сработало. Похоже, так будет лучше.

РЕДАКТИРОВАТЬ: Это, кажется, твердое решение: http://www.epicserve.com/blog/2012/feb/7/my-notes-cron-directory-etccrond-ubuntu-1110/

* * * * * root su --session-command="comand-that-needs-env-vars" user1 -l
...