¿Cómo hacer que el servicio de Unix vea las variables de entorno?

52

He configurado mi variable de entorno usando /etc/profile:

export VAR=/home/userhome

Entonces si lo hago echo $VARse nota/home/userhome

Pero cuando pongo referencia a esta variable en el /etc/init.d/servicenamearchivo, no puede encontrar esta variable. Cuando ejecuto service servicename statususando un /etc/init.d/servicenamearchivo con el siguiente contenido:

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

dice /dir: No such file or directory

Pero funciona si corro en /etc/init.d/servicename statuslugar deservice servicename status

¿Cómo puedo hacer que el servicio de Unix vea las variables de entorno?

altern
fuente
Nota que la invocación del Sistema 5 rcguión directamente también no funciona de esa manera en los sistemas operativos systemd, como todas las invocaciones de la secuencia de comandos se convierten en invocaciones de systemctlpor un gancho oculto.
JdeBP

Respuestas:

70

El problema es servicequitar todas las variables de entorno pero TERM, PATHy LANGque es algo bueno. Si está ejecutando el script directamente, nada elimina las variables de entorno, por lo que todo funciona.

No desea confiar en variables de entorno externas porque al inicio la variable de entorno probablemente no esté presente y su sistema de inicio probablemente no la configure de todos modos.

Si aún desea confiar en tales variables, obtenga un archivo y lea las variables de él, por ejemplo, cree /etc/default/servicenamecon el contenido:

VAR=value

y fuente de su script de inicio, por ejemplo:

[ -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
fuente
13
Muy servicial, gracias. Para otros novatos de Linux, aquí están las cosas crípticas de Bash. [ ... ]es una abreviatura para una prueba condicional; ver esta respuesta . -fes un ifargumento para verificar si el archivo existe. &&es un operador de cortocircuito: solo .ejecute el segundo comando si el primero sale con 0. operador de origen o punto: lea y ejecute comandos desde el argumento del nombre de archivo. -zes un ifargumento para verificar una cadena de longitud cero. >&2enviar salida a stderr. Ver también Introducción a if .
Mark Berry
@MarkBerry -fes parte de [, no if.
Chris Down
@ ChrisDown, gracias. Entonces " [ ... ]es una abreviatura de un testcomando condicional ; vea esta respuesta . -fEs un testargumento para verificar si existe un archivo".
Mark Berry
@MarkBerry Correcto. Puede pensar en [(o test) como solo otro comando: todo lo que ifhace es tomar alguna acción en función del estado de salida.
Chris Down
Me he encontrado con una situación similar a esta, pero no necesito $VARestar en el guión de inicio, necesito que esté disponible para un programa diferente 2 o 3 llamadas aguas abajo del guión de inicio. P.ej. La secuencia de comandos init llama a start-stop-daemon que llama al Programa 1 (Java) que llama al Programa 2 que necesita $VAR. Intenté el truco en esta respuesta, pero no parece funcionar en mi situación. ¿Cómo puedo asegurarme de que $VARestará disponible para el Programa 2?
FrustratedWithFormsDesigner
1

En mi caso, necesitaba una RAILS_ENVque se encuentra en /etc/bash.bashrc: export RAILS_ENV=staging. Agregué $(grep RAILS_ENV /etc/bash.bashrc)y eso hizo que la variable estuviera disponible para el script. Lo hice de esta manera para no tener que incluir el resto del archivo.

geermc4
fuente
-1

Una solución fea que también 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
fuente