Как заставить CRON вызывать правильные пути


124

Я пытаюсь заставить cron вызывать правильные PATH. Когда я запускаю скрипт Python из оболочки, скрипт работает нормально, так как он использует PATH, заданные в bashrc, но когда я использую cron, все PATH не используются из bashrc. Есть ли файл, в который я могу ввести PATH для cron, например bashrc, или способ вызвать PATH из bashrc?

Извините, я не думаю, что я сформулировал это правильно, я могу получить правильный сценарий для запуска (это означает, что путь к сценарию в crontab здесь не является проблемой), просто когда этот сценарий выполняется, я запускаю сборку, и здесь используется Пути установлены в .bashrc. Когда я запускаю скрипт, когда я вхожу в систему, .bashrcменяются пути PATH. Поскольку cron не запускается в оболочке, как говорится, он не втягивается .bashrc. Есть ли способ вытащить это без написания оболочки сценария bash?


также ознакомьтесь с приведенным здесь предложением о том, как заставить настройки bashrc работать для cronjobs: stackoverflow.com/q/15557777/1025391
moooeeeep

2
Волшебная, простая и правильная команда для включения вашего профиля в текущую среду: source /etc/profileон должен есть .bashrcи многое другое, что вам может не хватать. Явный поиск профилей становится очень полезным, если вы хотите, чтобы некоторые скрипты выполнялись «автономно», он также защищает от странных сред и так далее ...
exa

1
@exa +100 Это заставляет shскрипты, вызываемые crontab, работать. Вы можете подтвердить, что он обновляет путь, добавив задание, например, * * * * * echo $PATH > ~/crontab_path.txtи проверив файл через минуту.
geotheory

Ответы:


177

Я использовал /etc/crontab. Я использовал viи ввел в этот файл нужные мне пути и запустил его как root. Обычный crontab перезаписывает заданные вами пути. Хороший учебник, как это сделать .

Общесистемный файл cron выглядит так:

This has the username field, as used by /etc/crontab.
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file.
# This file also has a username field, that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user   command
42 6 * * *   root    run-parts --report /etc/cron.daily
47 6 * * 7   root    run-parts --report /etc/cron.weekly
52 6 1 * *   root    run-parts --report /etc/cron.monthly
01 01 * * 1-5 root python /path/to/file.py

17
Это работает с crontab -e на уровне пользователя, и это также безопаснее.
Роберт Бризита

2
Могу ли я использовать bash вместо sh?
ответила

1
мне кажется странным, что ПУТЬ по умолчанию, установленный в / etc / crontab, как показано @chrissygormley, а также установленный в моем (Ubuntu) crontab, отличается от пути в / etc / environment, в частности, он помещает / sbin и / bin перед / usr / sbin и / usr / bin. Теперь я изменил это в моем / etc / crontab, чтобы сделать его таким же, как пользовательская среда.
scoobydoo

У меня не работает .. Я выводю содержимое cron в файл. Cron запускается, файл создается, но не помещает в него никакого содержимого.
Volatil3

2
Кажется, что не все установленные пути /etc/crontabдоступны для cron при запуске с правами root в Ubuntu 14.04. ( sudo crontab -e)
Дэвид Оливер

50

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

* * * * * env > env_dump.txt

Сравните это с выводом envв обычном сеансе оболочки.

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

Вот быстрое исправление, которое можно добавить $PATHк текущему crontab:

# echo PATH=$PATH > tmp.cron
# echo >> tmp.cron
# crontab -l >> tmp.cron
# crontab tmp.cron

Полученный crontab будет похож на ответ Криссигормли, с PATH, определенным до правил crontab.


22

Вы должны поместить полные пути в свой crontab. Это самый безопасный вариант.
Если вы не хотите этого делать, вы можете поместить вокруг своих программ сценарий-оболочку и указать там PATH.

например

01 01 * * * command

будет выглядеть так:

01 01 * * * /full/path/to/command

Кроме того, все, из чего вызывается, cronдолжно быть очень осторожно с программами, которые оно запускает, и, вероятно, устанавливать свой собственный выбор для PATHпеременной.

РЕДАКТИРОВАТЬ:

Если вы не знаете, где находится команда, которую хотите выполнить which <command>из оболочки, она сообщит вам путь.

EDIT2:

Итак, когда ваша программа запущена, первое, что она должна сделать, это установить PATHи любую другую необходимую переменную (например LD_LIBRARY_PATH) на значения, которые требуются для запуска скрипта.
По сути, вместо того, чтобы думать о том, как изменить среду cron, чтобы сделать ее более подходящей для вашей программы / скрипта, сделайте так, чтобы ваш скрипт обрабатывал заданную среду, установив соответствующую при запуске.


1
если это на вашем пути, используйте 'which command', и он даст вам полный путь
Пол Уилан

@Douglas Leeder - Когда вы говорите поместить полный путь в cron, вы имеете в виду поместить его в crontab или другой файл? Если это так, как бы вы это сделали, если команда cron: '01 01 * * * command '. Спасибо
Криссигормли 05

@chrissygormley - Да crontab.
Дуглас Лидер, 05

Извините, должно быть некоторая путаница. Я изменил формулировку вопроса выше.
Криссигормли 05

16

Установка PATH прямо перед командной строкой в ​​моем crontab сработала для меня:

* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing

предпочитаю этот путь. или укажите полный путь к скрипту.
zw963

5
Я не думаю, что путь будет продолжать расти, каждый раз, когда он запускается в новой среде, со свежей копией PATH ...
jjcf89

Можно подтвердить, что @ jjcf89 правильный, PATH обновляется при каждом запуске.
electrovir

14

Добавление определения PATH в пользовательский crontab с правильными значениями поможет ... Я заполнил свое:

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

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


1
Для пользователя crontab это должен быть правильный ответ. Не все в системе могут редактировать /etc/crontab. Это самый простой ответ на уровне пользователя. Хорошая работа, @ Treviño. Проголосуйте за это, если согласны.
frederickjh

14

Сделайте так, чтобы ваши переменные работали на вас, это позволит получить доступ к t

Определите ваш PATH в /etc/profile.d/*.sh

Общесистемные переменные среды

Файлы с расширением .sh в каталоге /etc/profile.d запускаются всякий раз, когда вводится оболочка входа в bash (например, при входе в систему с консоли или через ssh), а также с помощью DisplayManager при загрузке сеанса рабочего стола.

Например, вы можете создать файл /etc/profile.d/myenvvars.sh и установить такие переменные:

export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin

Запустите crontab с опцией входа!

CRONTAB запустить сценарий или команду с переменными среды

0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c 'php -f ./download.php'
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c download.sh

11

проблема

Ваш сценарий работает, когда вы запускаете его с консоли, но не работает в cron.

причина

В вашем crontab нет правильных переменных пути (и, возможно, оболочки)

Решение

Добавьте текущую оболочку и перейдите к crontab

Скрипт, который сделает это за вас

#!/bin/bash
#
# Date: August 22, 2013
# Author: Steve Stonebraker
# File: add_current_shell_and_path_to_crontab.sh
# Description: Add current user's shell and path to crontab
# Source: http://brakertech.com/add-current-path-to-crontab
# Github: hhttps://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

# function that is called when the script exits (cleans up our tmp.cron file)
function finish { [ -e "tmp.cron" ] && rm tmp.cron; }

#whenver the script exits call the function "finish"
trap finish EXIT

########################################
# pretty printing functions
function print_status { echo -e "\x1B[01;34m[*]\x1B[0m $1"; }
function print_good { echo -e "\x1B[01;32m[*]\x1B[0m $1"; }
function print_error { echo -e "\x1B[01;31m[*]\x1B[0m $1"; }
function print_notification { echo -e "\x1B[01;33m[*]\x1B[0m $1"; }
function printline { 
  hr=-------------------------------------------------------------------------------------------------------------------------------
  printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}"
}
####################################
# print message and exit program
function die { print_error "$1"; exit 1; }

####################################
# user must have at least one job in their crontab
function require_gt1_user_crontab_job {
        crontab -l &> /dev/null
        [ $? -ne 0 ] && die "Script requires you have at least one user crontab job!"
}


####################################
# Add current shell and path to user's crontab
function add_shell_path_to_crontab {
    #print info about what's being added
    print_notification "Current SHELL: ${SHELL}"
    print_notification "Current PATH: ${PATH}"

    #Add current shell and path to crontab
    print_status "Adding current SHELL and PATH to crontab \nold crontab:"

    printline; crontab -l; printline

    #keep old comments but start new crontab file
    crontab -l | grep "^#" > tmp.cron

    #Add our current shell and path to the new crontab file
    echo -e "SHELL=${SHELL}\nPATH=${PATH}\n" >> tmp.cron 

    #Add old crontab entries but ignore comments or any shell or path statements
    crontab -l | grep -v "^#" | grep -v "SHELL" | grep -v "PATH" >> tmp.cron

    #load up the new crontab we just created
    crontab tmp.cron

    #Display new crontab
    print_good "New crontab:"
    printline; crontab -l; printline
}

require_gt1_user_crontab_job
add_shell_path_to_crontab

Источник

https://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

Пример вывода

Пример вывода add_curent_shell_and_path_to_crontab.sh


3

В моем AIX cron берет переменные окружения из / etc / environment, игнорируя то, что установлено в .profile.

Изменить: я также проверил пару ящиков Linux разного возраста, и они, похоже, тоже имеют этот файл, так что это, вероятно, не специфично для AIX.

Я проверил это с помощью предложения cron joemaller и проверки вывода до и после редактирования переменной PATH в / etc / environment.


3

Если вы не хотите делать одни и те же правки в разных местах, сделайте примерно следующее:

* * * * * . /home/username/.bashrc && yourcommand all of your args

Файл. пробел, а затем путь к .bashrc и команда && - это волшебство, позволяющее внести изменения вашей среды в работающую оболочку bash. Кроме того, если вы действительно хотите, чтобы оболочка была bash, неплохо было бы иметь строку в вашем crontab:

SHELL=/bin/bash

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


2

Среда по умолчанию для заданий cron очень разреженная и может сильно отличаться от среды, в которой вы разрабатываете свои сценарии python. Для сценария, который может запускаться в cron, любая среда, от которой вы зависите, должна быть установлена ​​явно. В самом файле cron укажите полные пути к исполняемым файлам python и к вашим сценариям python.


2

Я знаю, что на это уже был дан ответ, но я подумал, что он будет полезен некоторым. У меня была аналогичная проблема, которую я недавно решил ( нашел здесь ), и вот основные шаги, которые я предпринял, чтобы ответить на этот вопрос:

  1. убедитесь, что у вас есть необходимые переменные в PYTHONPATH (можно найти здесь и здесь, а для получения дополнительной информации здесь) внутри .profile или .bash_profile для любой оболочки, в которой вы хотите протестировать свой скрипт, чтобы убедиться, что он работает.

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

    a) обязательно включите корневой каталог в переменную PATH (.), как описано здесь (в основном, если вы запускаете исполняемый файл с вашей командой, он должен иметь возможность найти корень или каталог, в котором хранится исполняемый файл) и, возможно, эти (/ SBIN: / бен: / USR / SBIN: / USR / BIN)

  3. в вашем файле crontab создайте задание cron, которое изменит каталог на каталог, в котором вы успешно запускали сценарий ранее (например, Users / user / Documents / foo)

    а) Это будет выглядеть так:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    

2

@Trevino: ваш ответ помог мне решить мою проблему. Однако для новичка постараюсь дать пошаговый подход.

  1. Получите текущую установку Java через $ echo $JAVA_HOME
  2. $ crontab -e
  3. * * * * * echo $PATH- это позволяет понять, какое значение PATH использует crontab в настоящее время. Запустите crontab и получите значение $ PATH, используемое crontab.
  4. Теперь снова отредактируйте crontab, чтобы установить желаемый путь к java bin: a) crontab -e; б) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin(это примерный путь); c) теперь ваше запланированное задание / сценарий вроде */10 * * * * sh runMyJob.sh &: г) удалить echo $PATHиз crontab, поскольку он сейчас не нужен.

2

Установите требуемый PATH в вашем cron

crontab -e

Изменить: Нажмите i

PATH=/usr/local/bin:/usr/local/:or_whatever

10 * * * * your_command

Сохранить и выйти :wq


1

Самый простой способ обхода, который я нашел, выглядит так:

* * * * * root su -l -c command

В этом примере вызывается su как пользователь root и запускается оболочка с полной средой пользователя, включая $ PATH, установленной так, как если бы они вошли в систему. Он работает одинаково в разных дистрибутивах, более надежен, чем поиск .bashrc (который не работал для me) и избегает жесткого кодирования конкретных путей, что может быть проблемой, если вы предоставляете пример или инструмент настройки и не знаете, какой дистрибутив или макет файла в системе пользователя.

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


-3

Если вы используете, webminто следующие шаги, как установить PATHзначение:

System
  -> Scheduled Cron Jobs
       -> Create a new environment variable
            -> For user: <Select the user name>
            -> Variable name: PATH
            -> Value: /usr/bin:/bin:<your personal path>
            -> Add environment variable: Before all Cron jobs for user
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.