Variables de entorno en bash

TLDR: coloca las definiciones en bashrc (/etc/bash.bashrc, o ~/.bashrc), antes del (posible) chequeo de interactividad.

Bash distingue entre entorno de inicio (login) y entorno interactivo.

En la mayoría de los casos, el entorno es interactivo (obviamente, ya que introducimos comandos “a mano”). Si ejecutamos un script bash (directamente, tipo “./mi_script”, o explicitando bash, tipo “bash -c mi_script” o “bash mi_script”), obviamente se considera “no interactivo”. Tampoco se considera interactivo la ejecución a través de la entrada estándar (por ejemplo, “echo ls | bash”). Si llamamos explícitamente a bash (por ejemplo, dentro de un terminal ejecutamos “bash”), sí se considera interactivo. En este sentido, a la primera ejecución de bash se le asigna el nivel 1 (“top level“), y a las sucesivas “sub-ejecuciones” se les va incrementando el nivel (con lo que dejan de ser “top-level”)

El entorno “de inicio” sólo lo “experimentamos” cuando entramos en el sistema (en local) o abrimos un terminal (en local). Estas sesiones se pueden identificar por el guión prefijo (“-bash” en lugar de “bash”).

Cuando ejecutamos un comando “directamente” (con su o ssh), el entorno no es ni de inicio ni interactivo.

Todo este trabalenguas tiene su importancia a la hora de definir variables de entorno, como PATH o LD_LIBRARY_PATH. Normalmente, se pueden colocar indistintamente en profile o en bashrc. Pero si necesitamos dichas variables en un entorno “no de inicio”, profile ya no nos vale.

Nos queda bashrc, que se procesa siempre… siempre que no haya una comprobación tipo…


# If not running interactively, don't do anything
[ -z "$PS1" ] && return

en cuyo caso, se ignora todo el código después del return.

Con lo cual, lo más seguro es lo que dice el TLDR (ver comienzo del artículo 😉 )

La única pega de este modelo es que, si vamos abriendo un entorno dentro de otro (ejecutando bash dentro de otro bash), las definiciones se pueden ir acumulando.

Un primer paso a la hora de resolver problemas de carga de configuraciones es mirar que tipo de shell se está usando en el caso de interés.

Si por ejemplo se necesita que ciertas variables estén disponibles al acceder por ssh, comprobamos el tipo de shell que se usa al entrar con ssh. Si empieza con “-“, ya sabemos que es una “shell de inicio”, con lo cual es mejor definir las variables en ficheros como ~/.profile.

Otra forma de averiguar el tipo de shell es imprimiendo la variable $- (opciones activas en la shell). Si la shell es interactiva, una de las letras sera la “i”.

La versión larga (resumida :-p )

En el fichero de código shell.c está la función run_startup_files() que es la que gestiona la carga de ficherros de configuración.

Resumiendo:

  • los intérpretes “no interactivos” no cargan ficheros de definiciones. Excepto que no esté en “modo POSIX” y no se llame “sh”, en cuyo caso se carga el fichero indicado en la variable BASH_ENV
  • cuando el intérprete es interactivo, o bash es llamado por su, la carga varía dependiendo de si es “login shell”. Cuando funciona como “login shell”, se cargan /etc/profile, ~/.profile, ~/.bash_profile y ~/.bash_login. En otro caso, se cargan /etc/bash.bashrc y ~/.bashrc
  • si bash funciona como una “top-level shell” ejecutada vía SSH, se carga ~/.bashrc.
  • si bash no está en “modo POSIX” y se llama con la opción –login (-l), se cargan las definiciones en /etc/profile, ~/.profile, ~/.bash_profile y ~/.bash_login
  • si bash está en “modo POSIX”, carga el fichero indicado en ENV

Visto de otro modo, ~/.bashrc se carga en los siguientes casos:

  1. top-level shell remota (ssh)
  2. shell interactiva no-de-inicio (su, ssh)

Curiosamente, en Debian 7.9 y posteriores (quizá antes de 7.9) no parece que se cargue automáticamente ~/.bashrc, con lo cual hay que cargarlo a mano desde ~/.profile

En builtins/evalfile.c:_evalfile encontramos las características que debe cumplir la ruta a cargar: que no sea un directorio a cargar (obvio), si no un fichero “normal” (“regular file”), que no sea demasiado grande, que no sea “binario” (por ejemplo, el fichero contiene más de 256 caracteres nulos), y que sea “correcto” sintacticamente.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *