Como fazer o serviço unix ver variáveis ​​de ambiente?

52

Eu configurei minha variável de ambiente usando /etc/profile:

export VAR=/home/userhome

Então, se eu fizer echo $VARisso mostra/home/userhome

Mas quando coloco referência a essa variável no /etc/init.d/servicenamearquivo, ela não pode encontrar essa variável. Quando executo service servicename statususando /etc/init.d/servicenamearquivo com o seguinte conteúdo:

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

diz /dir: No such file or directory

Mas funciona se eu correr em /etc/init.d/servicename statusvez deservice servicename status

Como posso fazer o serviço unix ver variáveis ​​de ambiente?

altern
fonte
Observe que invocar o rcscript System 5 diretamente também não funciona dessa maneira nos sistemas operacionais systemd, pois todas as invocações do script são transformadas em invocações systemctlpor um gancho oculto.
JdeBP

Respostas:

70

O problema é servicetiras todas as variáveis de ambiente, mas TERM, PATHe LANGque é uma coisa boa. Se você estiver executando o script diretamente, nada removerá as variáveis ​​de ambiente, para que tudo funcione.

Você não deseja confiar em variáveis ​​de ambiente externas, porque na inicialização a variável de ambiente provavelmente não está presente e seu sistema init provavelmente não a definirá de qualquer maneira.

Se você ainda deseja confiar nessas variáveis, obtenha um arquivo e leia as variáveis, por exemplo, crie /etc/default/servicenamecom o conteúdo:

VAR=value

e origine-o do seu script init, por exemplo:

[ -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
fonte
13
Muito útil, obrigado. Para outros iniciantes no Linux, aqui estão as coisas enigmáticas do Bash. [ ... ]é uma abreviação para um teste condicional; veja esta resposta . -fé um ifargumento para verificar se o arquivo existe. &&é um operador de curto-circuito: somente execute o segundo comando se o primeiro sair com 0. .operador de origem ou ponto: leia e execute comandos a partir do argumento filename. -zé um ifargumento para verificar uma cadeia de comprimento zero. >&2envia a saída para o stderr. Veja também Introdução ao if .
Mark Berry
@ MarkBerry -ffaz parte [, não if.
Chris Down
@ ChrisDown, obrigado. Então " [ ... ]é uma abreviação de um testcomando condicional ; veja esta resposta . -fÉ um testargumento para verificar se existe um arquivo".
Mark Marry
@MarkBerry Correct. Você pode pensar em [(ou test) apenas como outro comando - tudo o que iffaz é executar alguma ação com base no status de saída.
26415 Chris Down
Eu me deparei com uma situação semelhante a essa, mas não preciso $VARestar no script init, preciso que ele esteja disponível para um programa diferente 2 ou 3 chamadas a jusante do script init. Por exemplo. O script init chama start-stop-daemon que chama o Programa 1 (Java) que chama o Programa 2 que precisa $VAR. Eu tentei o truque nesta resposta, mas parece não funcionar na minha situação. Como posso garantir que $VARestará disponível para o Programa 2?
FrustratedWithFormsDesigner
1

No meu caso, eu precisava de um RAILS_ENVque foi definido em /etc/bash.bashrc: export RAILS_ENV=staging. Eu adicionei $(grep RAILS_ENV /etc/bash.bashrc)e isso disponibilizou a variável para o script. Fiz dessa maneira, para não precisar incluir o restante do arquivo.

geermc4
fonte
-1

Uma solução feia que também funcionará:

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
fonte