¿Cuál es la mejor forma independiente de distribución / shell para establecer variables de entorno?

31

La pregunta lo dice todo. Actualmente uso Arch Linux y zsh, pero me gustaría una solución que (como mínimo) funcione tanto en VT como en xterms y también (con suerte, preferiblemente) continuará funcionando si cambio distros o shells.

He escuchado respuestas muy dispares a esta pregunta en los documentos de diferentes distribuciones. Ubuntu dice "use .pam_environment". Creo que en Arch lo que recomiendan depende de tu caparazón. Actualmente pongo todo en .profile y si un shell no lo obtiene por alguna razón (por ejemplo, bash si existe .bash_profile), lo anulo al obtenerlo manualmente. Pero parece que debe haber una mejor manera.

Strugee
fuente
2
Esto no tiene nada que ver con la distribución y todo que ver con shell. Sin embargo, no estoy seguro de que haya una forma portátil de hacerlo.
Joseph R.
Hmm Impresionante .
Strugee

Respuestas:

29

Desafortunadamente, no hay una ubicación totalmente portátil para establecer variables de entorno. Los dos archivos más cercanos son ~/.profile, que es la ubicación tradicional y funciona de fábrica en muchas configuraciones, y ~/.pam_environmentuna alternativa moderna, común pero limitada.

Que poner en ~/.pam_environment

~/.pam_environmentTodos los métodos de inicio de sesión que utilizan PAM leen el archivo y que tienen este archivo habilitado. Esto cubre la mayoría de los sistemas Linux hoy en día.

La principal ventaja de esto ~/.pam_environmentes que (cuando está habilitado) se lee antes de que se inicie el shell del usuario, por lo que funciona independientemente del tipo de sesión, el shell de inicio de sesión y otras complejidades. Incluso funciona para inicios de sesión no interactivos como su -c somecommandy ssh somecommand.

La principal limitación ~/.pam_environmentes que solo puede colocar tareas simples allí, no una sintaxis de shell compleja. La sintaxis de este archivo es la siguiente.

  • Los archivos se analizan línea por línea.
  • El espacio en blanco inicial se ignora.
  • Opcionalmente, puede comenzar líneas con exporty un solo espacio (no una pestaña, vaya figura).
  • Después de eso, cada línea debe tener la forma VAR=VALUEdonde VAR consiste en letras, dígitos y guiones bajos.
  • # comienza un comentario, no puede aparecer en un valor.
  • Si VALUE comienza con 'o "y contiene otra cita idéntica, entonces VAR se establece en la cadena entre las citas (se ignora todo después de la segunda cita). De lo contrario, VAR se establece en la cadena después del =signo.
  • Si no hay =, la variable se elimina del entorno.

Por otro lado, ~/.pam_environmentfunciona en una gran variedad de circunstancias. En el lado negativo, no puede tener ninguna configuración dinámica, como basar el valor de una variable en otra variable (por ejemplo, agregar un directorio a PATH) o usar la salida de un comando (por ejemplo, probar si hay un directorio o programa), y algunos Los caracteres ( #'", nueva línea) son imposibles o problemáticos de poner en el valor.

Que poner en ~/.profile

Este archivo debe tener una sintaxis sh portátil (POSIX). Solo use extensiones ksh o bash (matrices, [[ … ]]etc.) si sabe que su sistema tiene estos shells como /bin/sh.

Este archivo puede leerse mediante scripts en aplicaciones automatizadas, por lo que no debe llamar a programas que producen ningún resultado o llamada exec. Si desea hacerlo en los inicios de sesión en modo de texto, hágalo solo para shells interactivos. Ejemplo:

case $- in *i*)
  # Display a message if I have new mail
  if mail -e; then echo 'You have new mail'; fi
  # If zsh is available, and this looks like a text-mode login, run zsh
  case "`ps $PPID` " in
    *" login "*)
      if type zsh >/dev/null 2>/dev/null; then exec zsh; fi;;
  esac
esac

Este es un ejemplo de uso /bin/shcomo su shell de inicio de sesión y cambiar a su shell favorito. Vea también cómo puedo usar bash como mi shell de inicio de sesión cuando mi administrador del sistema se niega a permitirme cambiarlo

¿Cuándo ~/.profileno se lee en el inicio de sesión no gráfico?

Diferentes shells de inicio de sesión leen diferentes archivos.

Si su shell de inicio de sesión es bash

Bash lee ~/.bash_logino ~/.bash_profilesi existen en lugar de ~/.profile. Además, bash no lee ~/.bashrcen un shell de inicio de sesión, incluso si es interactivo. Para no tener que recordar estos caprichos nuevamente, cree un ~/.bash_profilecon las dos líneas siguientes:

. ~/.profile
case $- in *i*) . ~/.bashrc;; esac

Consulte también ¿Qué archivos de configuración deben usarse para configurar variables de entorno con bash?

Si su shell de inicio de sesión es zsh

Zsh lee ~/.zprofiley ~/.zlogin, pero no ~/.profile. Zsh tiene una sintaxis diferente de sh, pero puede leer ~/.profileen modo de emulación sh. Puede usar esto para su ~/.zprofile:

emulate sh -c '. ~/.profile'

Vea también Zsh no golpeando ~ / .profile

Si su shell de inicio de sesión es otro shell

No hay mucho que pueda hacer allí, aparte de usarlo /bin/shcomo su shell de inicio de sesión y su shell favorito (como fish) solo como un shell interactivo. Eso es lo que hago con zsh. Consulte más arriba para ver un ejemplo de invocación de otro shell ~/.profile.

Comandos remotos

Al invocar un comando remoto sin pasar por un shell interactivo, no todos los shells leen un archivo de inicio.

Ksh lee el archivo especificado por la ENVvariable, si logra pasarlo.

Bash lee ~/.bashrcsi no es interactivo (!) Y su proceso padre se llama rshdo sshd. Para que pueda comenzar ~/.bashrccon

if [[ $- != *i* ]]; then
  . ~/.profile
  return
fi

Zsh siempre lee ~/.zshenvcuando comienza. Úselo con precaución, ya que esto se lee en cada instancia de zsh, incluso cuando es una subshell donde ha establecido otras variables. Si zsh es su shell de inicio de sesión y desea usarlo para establecer variables solo para comandos remotos, use una protección: configure algunas variables ~/.profile, como MY_ENVIRONMENT_HAS_BEEN_SET=yes, y verifique esta protección antes de leer ~/.profile.

if [[ -z $MY_ENVIRONMENT_HAS_BEEN_SET ]]; then emulate sh -c '~/.profile'; fi

El caso de los inicios de sesión gráficos

Muchas distribuciones, administradores de pantalla y entornos de escritorio organizan la ejecución ~/.profile, ya sea explícitamente desde las secuencias de comandos de inicio o ejecutando un shell de inicio de sesión.

Desafortunadamente, no existe un método general para manejar combinaciones de distribución / DM / DE donde ~/.profileno se lee.

Si usa una sesión tradicional iniciada por ~/.xsession, este es el lugar donde debe establecer sus variables de entorno; hacerlo por abastecimiento ~/.profile(es decir . ~/.profile). Tenga en cuenta que en algunas configuraciones, los scripts de inicio del entorno de escritorio se volverán a generar ~/.profile.

Gilles 'SO- deja de ser malvado'
fuente
¿qué case $- in *i*)hacer?
qodeninja
2
@qodeninja Ejecuta las siguientes instrucciones (hasta que coincidan ;;o esac) si $-coincide con el patrón *i*, es decir, si $-contiene i, es decir, si el shell es interactivo.
Gilles 'SO- deja de ser malvado'
$-es una cadena de las opciones de shell configuradas actualmente. (como set -x) isignifica concha interactiva.
Peter Cordes
¿No puede simplemente obtener un archivo común, por ejemplo ~/.config/env, incluso sin emulación?
Kevin Suttle
1
@ StéphaneChazelas Esa es una visión purista. Sigo .profilecumpliendo con las conchas Bourne bastante antiguas, pero reconozco que a algunas personas simplemente no les importa. No tengo nada en contra de las personas que suponen que sh = bash para sus propios archivos, solo me importa si publican#!/bin/sh secuencias de comandos que usan funciones bash.
Gilles 'SO- deja de ser malvado'
4

Por lo que sé, no existe un estándar agnóstico de distribución y shell para configurar las variables de entorno.

El estándar más común y de facto parece ser /etc/profiley ~/.profile. El segundo más común parece ser /etc/environmenty ~/.pam_environment.

Me parece que toda la documentación que te encontré también ya la encontraste. Los enumero aquí de todos modos para los otros lectores.

  • Debian recomienda /etc/profiley ~/.profile( enlace ).
  • Ubuntu recomienda /etc/environmenty ~/.pam_environment( enlace ).
  • Arch Linux menciona, entre otros, /etc/profiley /etc/environment( enlace ).

Bonificación: un texto que cuestiona el uso y / o mal uso de /etc/environmentdebian ( enlace , última actualización 2008).

lesmana
fuente
Independientemente del archivo que use, aún se topará con una sintaxis incompatible entre diferentes shells.
Joseph R.
1
@JosephR. ¿No mantienen la mayoría de los proyectiles compatibilidad con versiones anteriores sh? Mientras te quedes con POSIX, habría pensado que estarías bien ...
evilsoup
1
AFAIK no puede asignar variables cshy amigos en la forma POSIX (necesita algo como seto setenv)
Joseph R.
0

Agregué el siguiente script ~ / bin / agnostic_setenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]="
   exit 0
endif

if ($#args == 2) then
   if ("$args[1]" =~ *csh*) then 
      echo "setenv $args[2]"
      exit 0
   else
      echo "export $args[1]=$args[2]"
      exit 0
   endif
endif

echo "setenv $args[2] $args[3]"

Y en ~ / .perl-homedir utilizo:

eval `${HOME}/bin/agnostic_setenv $shell PERL_HOMEDIR 0`

Un script similar para agnostic_unsetenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]"
   exit 0
endif

echo "unsetenv $args[2]"
exit 0
Kobi
fuente