Як змусити послугу 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 також не працює таким чином у системних операційних системах, оскільки всі виклики сценарію перетворюються на виклики systemctlприхованого гака.
JdeBP

Відповіді:


70

Проблема полягає у serviceпозбавленні всіх змінних умов середовища, але TERM, PATHі LANGце добре. Якщо ви виконуєте сценарій безпосередньо, нічого не видаляє змінні середовища, тому все працює.

Ви не хочете покладатися на зовнішні змінні середовища, тому що при запуску змінної середовища, ймовірно, немає, і ваша система init, ймовірно, не буде її встановлювати в будь-якому випадку.

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

VAR=value

і джерело його з вашого сценарію init, наприклад:

[ -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бути в скрипті init, мені потрібно, щоб він був доступний для іншої програми 2 або 3 виклику нижче за течією сценарію init. Напр. скрипт init викликає старт-стоп-демон, який викликає програму 1 (Java), яка викликає програму 2, яка потребує $VAR. Я спробував хитрість у цій відповіді, але це, здається, не спрацювало в моїй ситуації. Як я можу переконатися, що $VARпрограма 2 буде доступна?
FrustratedWithFormsDesigner

1

У моєму випадку, мені потрібно було , RAILS_ENVяка була встановлена в /etc/bash.bashrc: export RAILS_ENV=staging. Я додав $(grep RAILS_ENV /etc/bash.bashrc)і це зробив змінну доступною для сценарію. Я зробив це так, щоб мені не довелося включати решту файлів.


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