Как заставить сервис Unix видеть переменные окружения?

52

Я установил свою переменную среды, используя /etc/profile:

export VAR=/home/userhome

Тогда, если я делаю echo $VARэто показывает/home/userhome

Но когда я помещаю ссылку на эту переменную в /etc/init.d/servicenameфайл, она не может найти эту переменную. Когда я запускаю, service servicename statusиспользуя /etc/init.d/servicenameфайл со следующим содержанием:

case "$1" in
status)    
    cd $VAR/dir
    ;;
esac

это говорит /dir: No such file or directory

Но это работает, если я бегу /etc/init.d/servicename statusвместоservice servicename status

Как сделать так, чтобы сервис Unix видел переменные среды?

чередующееся
источник
Обратите внимание, что rcпрямой вызов сценария System 5 также не работает в операционных системах systemd, так как все вызовы сценария превращаются в вызовы systemctlскрытым хуком.
JdeBP

Ответы:

70

Проблема состоит в том serviceПолоски все переменные окружения , но TERM, PATHи LANGчто хорошо. Если вы выполняете сценарий напрямую, ничто не удаляет переменные среды, поэтому все работает.

Вы не хотите полагаться на внешние переменные среды, потому что при запуске переменная среды, вероятно, отсутствует, и ваша система инициализации, вероятно, не установит ее в любом случае.

Если вы все еще хотите полагаться на такие переменные, создайте файл и прочитайте переменные из него, например, создайте /etc/default/servicenameс содержимым:

VAR=value

и получить его из вашего скрипта инициализации, например:

[ -f /etc/default/service-name ] && . /etc/default/service-name

if [ -z "$VAR" ] ;  then
  echo "VAR is not set, please set it in /etc/default/service-name" >&2
  exit 1
fi

case "$1" in
status)    
    cd "$VAR"/dir
    ;;
esac
Ульрих Дангел
источник
13
Очень полезно, спасибо. Для других новичков в Linux, вот загадочные вещи Bash. [ ... ]сокращение от условного теста; увидеть этот ответ . -fявляется ifаргументом , чтобы проверить, существует ли файл. &&является оператором короткого замыкания: вторую команду следует выполнять только в том случае, если первая выходит с 0. .исходный или точечный оператор: читать и выполнять команды из аргумента имени файла. -zявляется ifаргументом для проверки строки нулевой длины. >&2отправить вывод в stderr. Смотрите также Введение в if .
Марк Берри
@MarkBerry -fявляется частью [, а не if.
Крис Даун
@ChrisDown, спасибо. Так что « [ ... ]это условное обозначение testкоманды; смотрите этот ответ . -fЭто testаргумент, чтобы проверить, существует ли файл».
Марк Берри
@MarkBerry Правильно. Вы можете думать о [(или test) как о просто другой команде - все, что ifнужно, это предпринять какое-то действие в зависимости от состояния выхода.
Крис Даун
Я столкнулся с ситуацией , подобной этой, но мне не нужно , $VARчтобы быть в сценарии инициализации, мне нужно, чтобы это было доступно для другой программы 2 или 3 вызова вниз по течению от самого сценария. Например. Скрипт init вызывает start-stop-daemon, который вызывает программу 1 (Java), которая вызывает нужную программу 2 $VAR. Я попробовал хитрость в этом ответе, но в моей ситуации это не сработало. Как я могу гарантировать, что $VARэто будет доступно для Программы 2?
FrustratedWithFormsDesigner
1

В моем случае, мне нужно было , RAILS_ENVкоторая была установлена в /etc/bash.bashrc: export RAILS_ENV=staging. Я добавил, $(grep RAILS_ENV /etc/bash.bashrc)и это сделало переменную доступной для скрипта. Я сделал это таким образом, чтобы мне не пришлось включать остальную часть файла.

geermc4
источник
-1

Одно уродливое решение, которое также будет работать:

function exec() {
    args=( $@ )
    command=${args[0]}
    dummy=${args[1]}
    whoami=`whoami`
    if [ -z "$dummy" ]; then
        me=`basename $0`
        runuser -l ${whoami} -c "bash /etc/init.d/${me} ${command} dummy"
    else
       printenv
   fi
}

case $1 in
    status)
        status
        ;;
    start|stop|kill|restart)
        exec $*
        ;;
    *)
        usage
esac
Максим
источник