Де я можу встановити змінні середовища, які використовуватиме crontab?


266

У мене є коронка, яка працює щогодини. Користувач, який працює за ним, має змінну середовище в тій .bash_profileроботі, коли користувач виконує завдання з терміналу, однак, очевидно, вони не підхоплюються crontab, коли він працює.

Я спробував встановити їх .profileі , .bashrcале вони до сих пір , здається, не отримати взяв. Хтось знає, куди я можу помістити варіювання середовища, яке може взяти crontab?

Відповіді:


88

Нехай 'cron' запустить скрипт оболонки, який задає середовище перед запуском команди.

Завжди.

#   @(#)$Id: crontab,v 4.2 2007/09/17 02:41:00 jleffler Exp $
#   Crontab file for Home Directory for Jonathan Leffler (JL)
#-----------------------------------------------------------------------------
#Min     Hour    Day     Month   Weekday Command
#-----------------------------------------------------------------------------
0        *       *       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/hourly
1        1       *       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/daily
23       1       *       *       1-5     /usr/bin/ksh /work1/jleffler/bin/Cron/weekday
2        3       *       *       0       /usr/bin/ksh /work1/jleffler/bin/Cron/weekly
21       3       1       *       *       /usr/bin/ksh /work1/jleffler/bin/Cron/monthly

Сценарії в ~ / bin / Cron - це всі посилання на один сценарій, 'runcron', який виглядає так:

:       "$Id: runcron.sh,v 2.1 2001/02/27 00:53:22 jleffler Exp $"
#
#       Commands to be performed by Cron (no debugging options)

#       Set environment -- not done by cron (usually switches HOME)
. $HOME/.cronfile

base=`basename $0`
cmd=${REAL_HOME:-/real/home}/bin/$base

if [ ! -x $cmd ]
then cmd=${HOME}/bin/$base
fi

exec $cmd ${@:+"$@"}

(Написано за допомогою старого стандарту кодування - сьогодні я б на початку використовував шебанг "#!".)

'~ / .Cronfile' - це зміна мого профілю для використання cron - суворо неінтерактивна і не повторюється заради шуму. Ви можете домовитись виконувати .profile тощо. (Речі REAL_HOME - артефакт мого оточення. Ви можете зробити вигляд, що він такий самий, як $ HOME.)

Отже, цей код зчитує відповідне середовище, а потім виконує не-Cron версію команди з мого домашнього каталогу. Наприклад, наприклад, моя команда "будній день" виглядає так:

:       "@(#)$Id: weekday.sh,v 1.10 2007/09/17 02:42:03 jleffler Exp $"
#
#       Commands to be done each weekday

# Update ICSCOPE
n.updics

Команда "щодня" простіша:

:       "@(#)$Id: daily.sh,v 1.5 1997/06/02 22:04:21 johnl Exp $"
#
#       Commands to be done daily

# Nothing -- most things are done on weekdays only

exit 0

246

Ви можете визначити змінні середовища в самому crontab під час запуску crontab -eз командного рядка.

LANG=nb_NO.UTF-8
LC_ALL=nb_NO.UTF-8
# m h  dom mon dow   command

* * * * * sleep 5s && echo "yo"

Ця функція доступна лише для певних реалізацій cron. В даний час Ubuntu і Debian використовують vixie-cron, що дозволяє їх оголошувати у файлі crontab (також GNU mcron ).

Archlinux та RedHat використовують кроні, яка не дозволяє оголошувати змінні середовища і викидатиме синтаксичні помилки в cron.log. Обхід може бути виконаний за кожний запис:

# m h  dom mon dow   command
* * * * * export LC_ALL=nb_NO.UTF-8; sleep 5s && echo "yo"

58
Зауважте, що ви не можете використовувати заміну змінної як у оболонці, тому декларація на зразок PATH = / usr / local / bin: $ PATH інтерпретується буквально.
Зак

8
Я зміг встановити змінні середовища в самому кронтабі під RedHat 4.4.7-3 та cronie-1.4.4-15.el6.x86_64
Бруно Ланге

7
Вам не потрібно експортувати змінні, якщо змінні використовуються лише в межах команди, просто додайте їх перед вашою командою. "* * * * * сон 5s; LC_ALL = nb_NO.UTF-8 echo $ LC_ALL"
vutran


@BrunoLange Ви могли б поділитися пелясом, як вам вдалося їх налаштувати?
Newskooler

145

У мене є ще одне рішення цієї проблеми:

0 5 * * * . $HOME/.profile; /path/to/command/to/run

У цьому випадку він вибере всю змінну середовища, визначену у вашому $HOME/.profileфайлі.

Звичайно $HOME, також не встановлено, ви повинні замінити його на повний шлях вашого $HOME.


Це працювало для мене після того, як багато намагалися знайти відповідь, дякую!
vladimir montealegre

5
це не спрацювало для мене до тих пір, поки я не зрозумів, що покинув цей період, що передував $ HOME. Що, власне, робить цей період?
мухомор

9
Період еквівалентний команді "джерело": tldp.org/LDP/abs/html/special-chars.html#DOTREF
Jeff W

@PeterLee чи щось згадане працювало для вас? Я написав це, оскільки вищезгадані рішення для мене не були ефективними. Якщо вищезгадане рішення не допоможе, мені доведеться провести кілька досліджень, щоб знайти причину. ;-)
Вішал

3
@Vishal Насправді це зараз працює для мене. Я намагався source ~/.bashrc, і виявляється, що мій .bashrcфайл начебто конфліктує із завданням cron. Якщо я використовую дуже простий .env_setup_rcфайл із лише одним рядком:, export MY_ENV_VAR=my_env_valвін фактично працює. Дивіться мій пост: stackoverflow.com/questions/15557777/…
Пітер Лі

63

Встановлення VAR /etc/environmentтакож працювало для мене в Ubuntu. Станом на 12.04, змінні в /etc/environmentзавантажуються на cron.


11
Найкраща відповідь, просто виконайте, env >> /etc/environmentі всі поточні середовища тепер доступні в CRON-роботах.
Савагеман

6
це чудово працює для мене. тим більше, що я біжу в контейнер Docker, тому я не дуже переймаюся наслідками "системних".
Лукас Поттерський

14
@ Савагеман - це як вбивство мух з термоядерними бомбами, також ставки несподіваної поведінки надзвичайно великі.
Fran Marzoa

2
Будьте обережні: не env >> /etc/environmentвдасться, якщо в одній із змінних оточення є хеш-знак. Мені найважче було вирішити проблеми з моєю програмою. Це виявився паролем, що містить "#", який на цьому кроці стає усіченим.
asac

3
Це має бути обрана відповідь. Я не знаю, чому люди ускладнюють речі з іншими відповідями або з цими матеріалами про env >> / тощо / оточення. Просто моргніть добре редагувати тощо / середовище, якщо ви хочете, щоб ці середовища були загальнодоступними: мої експерименти, схоже, підтверджують, що заяви про експорт для env vars в / etc / Environment доступні для crontab, а також для користувачів. ПРОБЛЕМА: знову ж таки з моїх експериментів: виявляється, що ці околиці НЕ розширюються в межах самої crontab! ... тобто вони розширені лише в сценаріях, що називаються!
гризун

39

Якщо ви запускаєте сценарії, які ви виконуєте через cron за допомогою:

#!/bin/bash -l

Вони повинні підбирати ваші ~/.bash_profileзмінні середовища


4
Ця відповідь повинна отримати більше результатів і бути просто обраною відповіддю: Дуже проста та елегантна та уникає незліченних хитрощів, які потребують стрибків по всій системі.
JakeGould

Мені подобається ця відповідь +1. Може / Чи слід це використовувати під час запуску rootcrontab? У /home/rootмоїй системі немає папки, і тому я не бачу, як це буде працювати з rootcrontab 's. Ідеї?
Сеамус

У самому сценарії. Котрий потім ти нормально працюєш із cron.
breizhmg

@Jim див. Цей приклад , використовується класичний виконуваний файл (chmod 777) #!/bin/bash. Магія тут - додати-l
Пітер Краус

22

Розширення прикладу @carestad, що мені здається легше, - це запустити сценарій cron і створити середовище в сценарії.

У файлі crontab -e:

SHELL=/bin/bash

*/1 * * * * $HOME/cron_job.sh

У файлі cron_job.sh:

#!/bin/bash
source $HOME/.bash_profile
some_other_cmd

Будь-яка команда після джерела .bash_profile матиме ваше оточення так, ніби ви ввійшли в систему.


16

Для мене мені довелося встановити змінну оточення для програми php. Я змінив його, додавши наступний код до мого crontab.

$ sudo  crontab -e

crontab:

ENVIRONMENT_VAR=production

* * * * * /home/deploy/my_app/cron/cron.doSomethingWonderful.php

і всередині doSomethingWonderful.php я міг отримати значення середовища за допомогою:

<?php     
echo $_SERVER['ENVIRONMENT_VAR']; # => "production"

Я сподіваюся, що це допомагає!


Це не спрацювало для мене. Змінна середовища не була доступна в сценарії, який викликався всередині crontab.
Nikhil

12

Все, що ви налаштуєте, crontabбуде доступне в cronjobs, як безпосередньо, так і за допомогою змінних у скриптах.

Використовуйте їх у визначенні кроні

Ви можете налаштувати crontabтак, що він встановлює змінні, які потім можуть використовувати cronjob:

$ crontab -l
myvar="hi man"
* * * * * echo "$myvar. date is $(date)" >> /tmp/hello

Тепер файл /tmp/helloпоказує такі речі:

$ cat /tmp/hello 
hi man. date is Thu May 12 12:10:01 CEST 2016
hi man. date is Thu May 12 12:11:01 CEST 2016

Використовуйте їх у сценарії, який виконує cronjob

Ви можете налаштувати crontabтак, що він встановлює змінні, які потім можуть використовувати сценарії:

$ crontab -l
myvar="hi man"
* * * * * /bin/bash /tmp/myscript.sh

І скажіть, що сценарій /tmp/myscript.shтакий:

echo "Now is $(date). myvar=$myvar" >> /tmp/myoutput.res

Він створює файл, що /tmp/myoutput.resпоказує:

$ cat /tmp/myoutput.res
Now is Thu May 12 12:07:01 CEST 2016. myvar=hi man
Now is Thu May 12 12:08:01 CEST 2016. myvar=hi man
...

7

Розширення на @Robert Brisita просто розширилося, також якщо ви не хочете налаштувати всі змінні профілю в сценарії, ви можете вибрати змінні, які потрібно експортувати у верхній частині сценарію

У файлі crontab -e:

SHELL=/bin/bash

*/1 * * * * /Path/to/script/script.sh

У script.sh

#!/bin/bash
export JAVA_HOME=/path/to/jdk

some-other-command

7

Замість

0  *  *  *  *  sh /my/script.sh

Використовуйте bash -l -c

0  *  *  *  *  bash -l -c 'sh /my/script.sh'

1
Чому це замість просто декларації Bash у верхній частині файлу має -lтаке #!/bin/bash -l:? Ця інша відповідь проста і елегантна.
JakeGould

1
Що робити, якщо мені потрібно запустити сценарій perl / python / ruby, а не башти? Я не можу додати #! / Bin / bash -l до верхньої частини сценарію python.
Ілля Харламов

"Що робити, якщо мені потрібно запустити сценарій perl / python / ruby, а не башти?" Досить справедливо. Але на мій погляд, ви можете написати просту оболонку сценарію Bash, яка потім викликає сценарій Python. Я роблю подібну річ для скриптів PHP. Причина полягає в тому, що блокування процесів набагато краще і надійніше в Bash, але сценарії Bash все ще головний біль. Тому я написав речі в PHP для складних матеріалів і дозволю Башу впоратися з рештою.
JakeGould

3

Я використовую Oh-my-zshв своєму macbook, тому я спробував багато речей для того, щоб виконати завдання crontab, але, нарешті, моє рішення було .zshrcпередбачити команду перед запуском.

*/30 * * * * . $HOME/.zshrc; node /path/for/my_script.js

Це завдання виконується кожні 30 хвилин і використовує .zshrcпрофіль для виконання моєї команди вузла.

Не забудьте використати крапку перед $HOMEваром.


2

Інший спосіб - натхненний цією відповіддю - "впорскувати" змінні - це наступний (приклад fcron):

%daily 00 12 \
    set -a; \
    . /path/to/file/containing/vars; \
    set +a; \
    /path/to/script/using/vars

Від help set:

-позначити змінні, які модифіковані або створені для експорту.

Використання +, а не - призводить до вимкнення цих прапорів.

Так все між ними set -і set +отримує експортується envі потім доступні для інших сценаріїв і т.д. Без використання setзмінних отримати , отримані , але жити в setтільки.

Крім цього, також корисно передавати змінні, коли програма вимагає запуску некореневого облікового запису, але вам знадобляться деякі змінні в середовищі іншого користувача. Нижче наведено приклад передачі в nullmailer vars для форматування заголовка електронної пошти:

su -s /bin/bash -c "set -a; \
                    . /path/to/nullmailer-vars; \
                    set +a; \
                    /usr/sbin/logcheck" logcheck

2

Я спробував більшість наданих рішень, але спочатку нічого не вийшло. Виявляється, що це не ті рішення, які не спрацювали. Мабуть, мій ~/.bashrcфайл починається із наступного блоку коду:

case $- in
    *i*) ;;
    *) return;;
esac

В основному це case statementте, що перевіряє поточний набір параметрів у поточній оболонці, щоб визначити, що оболонка працює в інтерактивному режимі. Якщо оболонка працює інтерактивно, вона переходить до пошуку ~/.bashrcфайлу. Однак в оболонці, на яку викликається cron, $-змінна не містить iзначення, яке вказує на інтерактивність. Тому ~/.bashrcфайл ніколи не отримується повною мірою. В результаті змінні середовища ніколи не встановлювалися. Якщо це сталося з вашою проблемою, сміливо коментуйте блок коду наступним чином та повторіть спробу:

# case $- in
#     *i*) ;;
#     *) return;;
# esac

Сподіваюся, це виявиться корисним


0

Ви також можете envдодати свою команду до введення змінних середовища так:

0 * * * *   env VARIABLE=VALUE /usr/bin/mycommand
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.