cron ігнорує змінні, визначені в ".bashrc" та ".bash_profile"


49

Я визначив змінну "SHELL" у файлі / etc / crontab:

[martin@martin ~]$ grep SHELL /etc/crontab 
SHELL=/usr/local/bin/bash
[martin@martin ~]$ file /usr/local/bin/bash
/usr/local/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 8.0 (800107), stripped
[martin@martin ~]$ 

Крім того, всі мої сценарії у файлі / etc / crontab запускаються під користувачем "martin". Однак /home/martin/.bash_profile (для оболонки для входу) та /home/martin/.bashrc (для оболонки без журналу) містять деякі змінні, які ігноруються у випадку роботи із cron, але використовуються у випадку, коли я заходжу в машину SSH або відкрити нову сесію bash. Чому cron ігнорує ці змінні? Хіба cron не просто виконує "/ usr / local / bin / bash my-script.sh" з дозволами для користувача "martin"?


2
Користувачі Ubuntu, можливо, хотіли б відзначити, що за замовчуванням Ubuntu .bashrcє лінія, яка не дозволяє їй працювати в неінтерактивних оболонках.
joeytwiddle

Відповіді:


72

Ви можете створити потрібний файл у верхній частині сценарію або на початку завдання для користувача, який виконує завдання. Команда "source" - це вбудована. Ви зробите те ж саме, якби внесли зміни до цих файлів, щоб завантажити зміни.

* * * * * source /home/user/.bash_profile; <command>

або

#!/bin/bash
source /home/user/.bash_profile

<commands>

2
Зауважте, що "джерело" може не працювати, якщо cron не використовує bashоболонку. Я додав відповідь, яка може справлятись із випадком, коли оболонка є sh.
Джонатан


23

Тому що це не інтерактивна оболонка. Те саме відбувається, коли ви відкриваєте деякі термінали.

Погляньте на це питання: Що таке файл .bashrc? | Супер Користувач

А також на цьому:

У чому різниця між .bashrc, .bash_profile та .en Environment? | Переповнення стеку

Різні сценарії спрацьовують залежно від того, з'єднання - оболонка для входу (чи ні), інтерактивна оболонка (чи ні) або те й інше.

Якщо ви хочете зробити bashrc, вам потрібно внести ці зміни:

Коли Bash запускається неінтерактивно, для запуску сценарію оболонки, наприклад, він шукає змінну BASH_ENV у середовищі, розширює його значення, якщо вона там відображається, і використовує розширене значення як ім'я файлу для читання та виконання . Bash поводиться так, ніби виконується наступна команда:

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi 

але значення змінної PATH не використовується для пошуку імені файлу.

Як зазначалося вище, якщо неінтерактивна оболонка викликається --loginпараметром, Bash намагається прочитати та виконати команди з файлів запуску оболонки для входу.

Джерело: Файли запуску Bash | Довідник по Bash | gnu.org


Отже, якщо ми встановимо BASH_ENV всередині Cron, скрипти bash cron будуть джерелом цього, оскільки cron не інтерактивний і не входить в систему.
CMCDragonkai

12

Ви не зможете запустити, sourceякщо використовується shоболонка. Це можна змінити, додавши наступний рядок у свій crontab:

SHELL=/bin/bash
* * * * * source "/root/.bashrc"; <command>

Ви також можете вказати середовище:

BASH_ENV="/root/.bashrc"
* * * * * <command>

або ви можете використовувати свій локальний, /home/user/.bashrcякщо це робота з крон користувача (наприклад crontab -e).

Зверніть увагу, що він .bash_profileможе замінити .bashrc, якщо він існує.

Кредит: Як змінити оболонку cron (sh на bash)?


це добре працює і для робочих завдань, запланованих у хмарному розкладі Acquia, які, в основному, є робочими місцями. Ви можете зробити те саме, як:SHELL=/bin/bash && source /home/YOUR_USER_NAME/.bash_profile && sh ....
Алехандро Морено

1

Щось інше, що може заважати пошуку джерел .bashrcз кронічного завдання, - це будь-які перевірки, які цей файл робить для виявлення інтерактивних оболонок.

Наприклад, для Ubuntu 18.04 за замовчуванням .bashrcдля користувача починається це:

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

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

і настільки джерело не принесе нічого корисного, оскільки він негайно вийде.


1

Ви можете викликати bash з такою -lопцією:

* * * * * /bin/bash -l /path/to/script arg1 arg2

Цей -lпараметр робить bash оболонкою для входу . Таким чином, він прочитає користувача .bash_profile. Він не буде читати користувача, .bashrcякщо його явно не встановлено .bash_profile. Це відбувається тому, що неінтерактивні оболонки не зчитуються автоматично .bashrc. Але вам не потрібно .bashrcмати роботу з cron, оскільки .bashrcце для налаштування корисних для інтерактивної оболонки.

Варіації:

Якщо bash знаходиться на PATH, не потрібно вказувати абсолютний шлях:

* * * * * bash -l /path/to/script arg1 arg2

Оптимізацією було б замінити поточну оболонку за допомогою exec:

* * * * * exec bash -l /path/to/script arg1 arg2

1

bashдіє по-різному, чи це оболонка, чи звичайна мова програмування (як-от perlабо python).

За дизайном, налаштування в ~/.bash_profile, ~/.bashrcі т. Д. Призначені для користувачів встановлювати речі, коли вони bashграють роль оболонки (оболонка для входу, інтерактивна оболонка). Подумайте про середовище, яке у вас є xterm(інтерактивна оболонка) або в sshсеансах (оболонка входу) або в консолі (оболонка входу).

З іншого боку, bashтакож є потужною розмовною мовою - думкою про багато сценаріїв для управління сервісами, systemd- що вимагає іншого стилю роботи. Наприклад, коли розробник пише системний сценарій або bashпрограму, він / вона не любить автоматично створювати джерело користувача ~/.bash_profile. Це звичайна програма, а не оболонка. Звичайна програма (включаючи bashпрограми) природно успадковувала б налаштування від поточної робочої зони (оболонки), але не встановлювала їх.

Якщо ми пишемо програму для cronin bash- це просто трапляється записати в bash; насправді, ми можемо записати його в pythonабо perlбудь-якої іншої progamming Мова-тоді ми можемо мати опцію джерела bash«s ~/.bash_profile(читай: настройка оболонки користувача, який як раз трапляється бути та сама мова вашої мови програмування):

[ -f /home/user/.bash_profile ] && . /home/user/.bash_profile

Однак що робити, якщо конкретний користувач не використовує bashйого як свою оболонку? Він / вона може використовувати zsh, ksh, fishі т.д. Таким чином, ця практика буде на самому ділі не працювати при написанні програми для громадського користування.

Отже, ви можете джерело, ~/.bash_profileякщо ви думаєте, що це спрацює. Але тут справа не в тому, чи зможемо ми створити файл, а в тому, як слід працювати в системі: концепція дизайну . Коротше кажучи: ми повинні розглядати bashяк щось, що має 2 ролі: оболонку та мову, що розповсюджується . Тоді все буде набагато простіше зрозуміти.


0

У мене була така ж проблема при виконанні програми для вузла з cron, яка використовує NVM. Для того, щоб змусити bash shell прочитати файл .bashrc з cron, якраз викликав команду bash з інтерактивною опцією оболонки `-l.

наприклад: * * * * * /bin/bash -lc '/home/user/myapp.sh restart'

Якщо це не працює, спробуйте встановити змінну шляху в crontab

41 7 * * * /bin/bash -lc "PATH=$PATH:/home/user/.nvm/versions/node/v8.10.0/bin && /home/user/script.sh restart "

-1

Мій спосіб вирішити це:

1) Введення моїх змінних у (кінець) ~/.profile:

myVarInDotProfile="someValue"

2) Створення сценарію Bash для моїх (щоденних) завдань ( ~/cronDaily.sh), що містять мої команди плюс повторювані джерела ~/.profle:

source ~/.profile
command ${myVarInDotProfile}/

3) планування виконання мого сценарію з crontabзапуску щодня:

0 0 * * * bash ~/cronDaily.sh

Моя змінна не була проігнорована, і команди успішно працювали.


Деякі можуть сказати, що таке інтенсивне пошуку ~/.profileпроблематично. У моєму конкретному випадку я не бачу, чому це проблема, але я б радив розглянути можливість створення спеціального файлу для цього.

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

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