Jak sprawić, by usługa unix widziała zmienne środowiskowe?

52

Ustawiłem zmienną środowiskową za pomocą /etc/profile:

export VAR=/home/userhome

Jeśli to zrobię, echo $VARto pokaże/home/userhome

Ale kiedy umieszczam odniesienie do tej zmiennej w /etc/init.d/servicenamepliku, nie może ona znaleźć tej zmiennej. Gdy uruchamiam service servicename statusprzy użyciu /etc/init.d/servicenamepliku o następującej treści:

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

to mówi /dir: No such file or directory

Ale działa, jeśli uruchomię /etc/init.d/servicename statuszamiastservice servicename status

Jak sprawić, by usługa unix widziała zmienne środowiskowe?

altern
źródło
Zauważ, że bezpośrednie wywoływanie rcskryptu System 5 również nie działa w ten sposób na systemowych systemach operacyjnych, ponieważ wszystkie wywołania skryptu są zamieniane w wywołania systemctlukrytego haka.
JdeBP

Odpowiedzi:

70

Problem polega na servicepaski wszystkie zmienne środowiskowe, ale TERM, PATHi LANGco jest dobrą rzeczą. Jeśli wykonujesz skrypt bezpośrednio, nic nie usuwa zmiennych środowiskowych, więc wszystko działa.

Nie chcesz polegać na zewnętrznych zmiennych środowiskowych, ponieważ podczas uruchamiania zmienna środowiskowa prawdopodobnie nie jest obecna, a Twój system init i tak prawdopodobnie jej nie ustawi.

Jeśli nadal chcesz polegać na takich zmiennych, pobierz plik i odczytaj z niego zmienne, np. Utwórz /etc/default/servicenamez zawartością:

VAR=value

i uzyskaj go ze skryptu init, np .:

[ -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
Ulrich Dangel
źródło
13
Bardzo pomocny, dzięki. Dla innych początkujących Linuksa, oto tajemnicze rzeczy Bash. [ ... ]jest skrótem dla testu warunkowego; zobacz tę odpowiedź . -fjest ifargumentem sprawdzającym, czy plik istnieje. &&jest operatorem zwarcia: .wykonuj drugie polecenie tylko wtedy, gdy pierwsze wyjdzie z 0. operatorem źródłowym lub kropkowym: czytaj i wykonuj polecenia z argumentu nazwa_pliku. -zjest ifargumentem sprawdzającym ciąg o zerowej długości. >&2wyślij wyjście do stderr. Zobacz także Wprowadzenie do if .
Mark Berry
@MarkBerry -fjest częścią [, a nie częścią if.
Chris Down
@ChrisDown, dzięki. Więc „ [ ... ]jest skrótem dla testpolecenia warunkowego ; zobacz tę odpowiedź . -fJest testargumentem sprawdzającym, czy plik istnieje”.
Mark Berry
@MarkBerry Correct. Możesz myśleć o [(lub test) jako o innym poleceniu - wystarczy ifpodjąć pewne działania w zależności od statusu wyjścia.
Chris Down,
Znalazłem sytuację podobną do tej, ale nie muszę $VARbyć w skrypcie inicjującym, muszę być dostępny dla innego programu 2 lub 3 wywołań poniżej skryptu inicjującego. Na przykład. skrypt init wywołuje start-stop-daemon, który wywołuje Program 1 (Java), który wywołuje Program 2, który potrzebuje $VAR. Próbowałem podstępu w tej odpowiedzi, ale wydaje się, że nie działa ona w mojej sytuacji. Jak mogę się upewnić, że $VARbędzie dostępny w Programie 2?
FrustratedWithFormsDesigner
1

W moim przypadku potrzebne RAILS_ENV, który został ustawiony w /etc/bash.bashrc: export RAILS_ENV=staging. Dodałem $(grep RAILS_ENV /etc/bash.bashrc)i dzięki temu zmienna stała się dostępna dla skryptu. Zrobiłem to w ten sposób, więc nie musiałem dołączać reszty pliku.

geermc4
źródło
-1

Jedno brzydkie rozwiązanie, które będzie działać:

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
Maksim
źródło