Как я могу загрузить переменные среды пользователя в cronjob?
У меня есть cronjob, который должен запускать скрипт каждую минуту на моей машине Ubuntu:
* * * * * /home/user/myscript.sh;
В этом скрипте я хочу использовать переменные среды, например $JAVA_HOME
и $M2_HOME
для автоматического запуска процесса сборки. Проблема в том, что эти переменные установлены в .bashrc
через export JAVA_HOME=/../..
.
Следовательно, я source
эти файлы перед выполнением моего скрипта:
* * * * * source ~/.bash_profile; source ~/.bashrc; /home/user/myscript.sh;
Однако переменные не установлены! Чтобы проверить это, я echo
переменные среды через env
в файл журнала:
env >> ~/env.log
echo $M2_HOME >> ~/env.log
В файле журнала все еще нет переменных. К файлу добавляются только следующие элементы (нет $M2_HOME
и т.д.):
LANGUAGE=en_US:en
HOME=/home/user
LOGNAME=user
PATH=/usr/bin:/bin
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/home/user
Если я запустил сценарий прямо в своей оболочке, все переменные распечатываются в env.log
.
То же самое происходит, когда я ставлю source
команды в файл сценария. Только если я удалю export
ключевое слово перед объявлением переменной это видно по echo $var
команда. Но это не решение, потому что я не управляю этими объявлениями.
Я попробовал решение @tripplee с ограниченной проблемой оболочки sh, но оно все равно не работает. Далее я сократил его до очень простого задания cron без второго скрипта, чтобы показать проблему:
* * * * * . $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;
cat /home/user/env.log
:
LANGUAGE=en_US:en
HOME=/home/user
LOGNAME=user
PATH=/usr/bin:/bin
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/home/user
Чтобы добавить к ответу tripleee, вы можете вызвать оценку всех ваших кронов в bash (или в оболочке по вашему выбору), указав оболочку в crontab.
SHELL=/bin/bash
* * * * * . $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;
редактировать и если вы действительно хотите увидеть, что он делает, следующая команда должна сделать его достаточно подробным:
/bin/bash -x -c '. $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log' > /tmp/cron.`date +\%s`
set -x
или флаг -x в командной строке заставит большинство оболочек печатать каждую вычисленную строку.
Для проверки в командной строке удалите \ из команды даты. Это необходимо, чтобы cron не оценивал% s как стандартный ввод.
Синтаксис задания cron ограничен sh
только чтобы вы не могли использовать башизмы вроде ~
. К счастью, исправить это просто - просто замените его на $HOME
. Так же, source
необходимо заменить на .
(просто точка).
Конечно, исходные скрипты не должны использовать синтаксис Bash, если вы собираетесь использовать их из sh
. Вероятно, самое простое решение - перенести эти вещи в ваш скрипт (или создать скрипт-оболочку для запуска Cron).
Потому что внутри вашего скрипта вы можете использовать bash
если хотите, при условии, конечно, что линия shebang правильно #!/bin/bash
(при необходимости измените путь), а не #!/bin/sh
.
Если вам это по какой-то причине не нравится, вы можете встроить Bash в свой crontab
файл, указав его явно:
* * * * * bash -c 'source ~/.bash_profile; source ~/.bashrc; ./myscript.sh'
Вы должны увидеть source: command not found
и export: command not found
в электронных письмах, отправленных cron
когда дела идут плохо. Изучение вывода ошибок действительно важно для устранения неполадок.
Конечно, если у вас есть стандартный .bashrc
в Ubuntu он немедленно выйдет из строя, если вы попытаетесь получить его из неинтерактивного скрипта. Может быть, лучше поместить нужные вам настройки для неинтерактивного использования в другой файл (возможно, .profile
который будет читать sh
по умолчанию)?
У тебя нет полный tty в cron. Но если вы запустите его через sudo -i
вы получите один.
* * * * * sudo -u user -i bash -c '. $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;'
Или для запуска скрипта:
* * * * * sudo -u user -i bash -c '. $HOME/.bash_profile; . $HOME/.bashrc; /home/user/myscript.sh;'
Если поставить source
команды в Баш скрипт, запускающий целевой скрипт, вы получите аккуратный:
* * * * * sudo -u user -i /home/user/mystarter.sh;