¿Dónde debo exportar una variable de entorno para que todas las combinaciones de bash / dash, interactivo / no interactivo, inicio de sesión / no inicio de sesión, lo recojan?

11

Aquí está la motivación para la pregunta:

Estoy usando Ubuntu 12.04 LTS 2 con el escritorio de Unity. En mi archivo .bashrc, agrego varios directorios a mi variable PATH y defino algunas variables de entorno, como JAVA_HOME. Cuando inicio aplicaciones desde una terminal (ejecutando bash, mi shell predeterminado), esto funciona muy bien, pero para varios de los accesos directos que usan el iniciador de Unity, ejecutan aplicaciones que parecen estar definidas para usar #! / Bin / sh, que tiene un alias para / bin / dash, y no recogen el contenido de ~ / .bashrc o ~ / .profile.

Supongo que podría cambiar todos estos accesos directos para usar / bin / bash en lugar de / bin / sh para forzarlo a recoger los cambios .bashrc, pero eso parece realmente extraño.

Dado que Ubuntu 12.04 (por defecto) alias / bin / sh a / bin / dash y que mi shell predeterminado es / bin / bash, ¿hay un solo lugar donde pueda elegir modificar la RUTA y definir variables de entorno si las quiero? estar presente en todas estas circunstancias:

  1. Cada vez que creo un shell bash sin inicio de sesión (usando la terminal en la unidad)
  2. Cada vez que creo un shell bash de inicio de sesión (por ejemplo, iniciar sesión de forma remota a través de ssh)
  3. Cada vez que uso un iniciador de aplicaciones de Unity (dado que el iniciador usa / bin / sh).
  4. Cada vez que se ejecuta un trabajo cron (dado que SHELL = / bin / sh en / etc / crontab).

Si entiendo correctamente, supongo que:

  • (1) / (2) y (3) / (4) son diferentes porque (1) / (2) son bash y (3) / (4) son guiones.
  • (1) y (2) son diferentes porque los archivos que bash elige cargar difieren dependiendo de si es o no un shell de inicio de sesión.
  • (3) y (4) son diferentes porque (3) vendrá en algún momento después de haber iniciado sesión (y, por lo tanto, ~ / .profile habrá sido obtenido por uno de sus procesos principales, mientras que (4) vendrá en algún momento punto en el que estoy , no inscrito, y por lo tanto ~ / .profile no habrá sido leída.

(No me sorprendería si también importan otros factores, como si el shell es interactivo o no, por lo que probablemente haya más combinaciones que ni siquiera había previsto ... Estoy feliz de que mi pregunta "mejore" " en ese caso.)

Esperaría que en algún momento, alguien debe haber hecho algún tipo de guía que le diga cómo / dónde modificar las variables de entorno de una manera independiente del shell (o al menos una forma compatible con guiones / bash) ... Simplemente puedo ' Parece que no encuentra los términos de búsqueda correctos para ubicar dicha guía.

¡Soluciones o punteros a soluciones muy apreciadas!

Actualizado:

  • Aclaración: este es el usuario predeterminado de Ubuntu creado por el proceso de instalación 12.04, por lo que no es nada lujoso. Que no tiene un ~ / .profile (que explícitamente fuentes de ~ / .bashrc), y la única ~ / .bash * archivos presentes son .bashrc, .bash_history y .bash_logout ... por lo que no hay ninguna .bash_profile.
  • Énfasis en el alcance: Realmente no me importan los shells que no sean el shell interactivo predeterminado (bash) y cualquier script que use / bin / sh (con alias para el guión), por lo que no hay necesidad de complicar esto con nada extra para tcsh / ksh / zsh / etc. apoyo.
Mickalot
fuente
2
Colóquelo en un archivo y luego deje que otros archivos rc lo obtengan.
konsolebox
De acuerdo con la página de manual del guión que tengo aquí, debería estar leyendo $ HOME / .profile para los shells de inicio de sesión.
Etan Reisner
@konsolebox ¿Qué archivos rc? AFAICT, dash no tiene un archivo rc. Y como dije, dash no parece estar recogiendo el contenido de ~ / .profile.
@EtanReisner Sí, y este es el punto de la pregunta. Cuando el guión no se ejecuta como un shell de inicio de sesión (y, por lo tanto, ~ / .profile no se obtiene), ¿entonces qué?
@Mickalot ¿Estás ejecutando dash interactivamente? Si no, intente agregarle la opción -l.
konsolebox

Respuestas:

9

La invocación de shell es algo complicado. Las páginas de manual de bash y dash tienen INVOCATIONsecciones sobre esto.

En resumen, dicen (hay más detalles en la página del manual, deberías leerlo):

When bash is                   | it reads
-------------------------------|----------
login shell                    | /etc/profile and then the first of ~/.bash_profile, ~/.bash_login or ~/.profile that exists.
                               |
interactive non-login shell    | /etc/bash.bashrc then ~/.bashrc
                               |
non-interactive shell          | The contents of $BASH_ENV (if it exists)
                               |
interactive (as "sh")          | The contents of $ENV (if it exists)

-

When dash is                   | it reads
-------------------------------|---------
login shell                    | /etc/profile then .profile
                               |
interactive shell              | The contents of ENV (it it exists, can be set in .profile as well as in initial environment)

No sé sobre otros proyectiles de forma manual, ya que nunca uso ninguno de ellos. Su mejor opción podría ser establecer un par de variables de entorno para apuntar a la secuencia de comandos de ubicación común y obtenerla manualmente (cuando corresponda) en los dos casos que no cubren.

Etan Reisner
fuente
Lamentablemente, el quid de este problema es el que falta en su tabla de tablero. Cuando el escritorio de Unity invoca cualquier script que comienza con #! / Bin / sh, lanza (lo que supongo que es) un shell de tablero no interactivo y sin inicio de sesión. Entonces la pregunta es: ¿cómo puedo hacer las mismas variables de entorno disponibles allí que están presentes en el resto de la matriz?
Derecha. Me imagino que es por eso que bash agregó BASH_ENV para ese espacio. Dado que el tablero no parece tener nada que funcione en esa ranura, no estoy seguro de que pueda resolver ese problema sin afectar el cambio en el entorno de la aplicación que inicia el tablero (de modo que el tablero lo herede). Esto requeriría que las variables de entorno se establezcan en su entorno X, que es donde entra en juego el comentario .xsession (rc) de @Mickalot. Esto todavía deja, como indicó, el elemento cuatro omitido (pero creo que en realidad es algo intencional).
Etan Reisner
Como estoy en Ubuntu 12.04 LTS, cron es en realidad pixie-cron, por lo que puedo definir las variables env en mi archivo crontab ... Supongo que SHELL = / bin / bash y BASH_ENV = ~ / .bashrc deberían hacerlo.
3

Entonces, hay varias formas de abordar esto. Muchas personas:

a. Tenga un archivo que tenga cosas comunes a todos sus shells de estilo sh, digamos .shcommony en cada uno de los .profile .bashrc .kshrcet cetra, solo obtenga esto con. .shcommon

si. Ponga todo .profiley obtenga esto de los otros archivos.

Las cosas que se necesitan para shells específicos o para shells interactivos versus no interactivos pueden ir al archivo apropiado antes de obtener .shcommon

Personalmente, no me gusta administrar varios archivos. Entonces, uso el siguiente enfoque:

Primero, todo lo que necesito entra .profile Ya que tengo algunas cosas específicas de bash y ksh, determino el nombre de shell actual usando lo siguiente:

# get name of current shell
# strip leading - from login shell
export SHELLNAME="${0#-}"

y luego tener comandos para shells específicos en algo como lo siguiente (algunos preferirían una declaración de caso).

if [ "$SHELLNAME" = 'bash' ]
then
    shopt -s checkwinsize

elif [ "$SHELLNAME" = 'ksh' ]
then
    stty erase ^?
fi

Si tengo comandos que solo deberían ejecutarse en shells interactivos, utilizo lo siguiente:

# check for interactive flag i in shell options $-
# in bash and ksh you could use the following, but breaks in dash
# if [[ $- == *i* ]]
if [ "$(echo $- | grep i)" != "" ]
then
  fortune
fi

Las cosas que son comunes en todas las conchas de estilo sh, por ejemplo, PATHpueden ir a la cima.

Luego, uso enlaces simbólicos para cargar este mismo archivo en todos los shells de estilo sh:

ln -s .profile .bashrc
ln -s .profile .kshrc

Un par de notas al margen, si tiene un .bash_profile, entonces bash cargará esto en lugar de .profiledash y ksh aún se cargará .profile Esto puede ser parte de su problema.

Además, es posible que desee considerar el uso #!/bin/bashen sus scripts en lugar de a #!/bin/dashmenos que realmente quiera scripts compatibles con POSIX. bash tiene muchas características adicionales que son muy agradables y se invoca dash o bash ya que sh deshabilitará muchas de estas características.

Además, la página de manual de bash hace un buen trabajo de explicar al .profilefrente .bashrcse carga. Reglas similares se aplican a ksh. dash se carga .profileal iniciar sesión y le permite cargar un archivo al inicio de shells interactivos que se especifica utilizando la ENVvariable de entorno en .profile(consulte también la página de manual de dash y busque .profile).


fuente
¿No podría simplemente probar $ 0 para el nombre del shell? ¿Hay conchas / casos donde eso no funciona?
Etan Reisner el
Del mismo modo, ¿verificar i en $ no es suficiente para la prueba de shell interactiva? (Se activará en shells interactivos sin un tty, pero eso puede ser o no un efecto secundario no deseado).
Etan Reisner
@Etan: Hrm, sé que intenté por primera vez $0y me encontré con problemas ... Sin embargo, parece que no recuerdo exactamente lo que eran. Iniciar sesión directamente en la consola se muestra $0como en -bashlugar de, bashpero eso podría remediarse.
@Etan: Sí, verificar si yo $-también funcionaría. ¿Tendría que pensar cuándo tendría un shell interactivo sin un tty? Su solución tiene una mejor "sensación" por alguna razón, puedo cambiar eso.
El -en -bashmedio "login shell", pero sí que habría que dar cuenta de que, en los lugares donde se prueba el valor o desea mostrar a alguien.
Etan Reisner
0

Dado que los casos (1) y (2) se resuelven obteniendo mis variables de entorno en .bashrc y .profile, la verdadera pregunta es "¿cuál es el nombre del archivo donde obtengo estas mismas variables para (3) y (4)?

Parece que hay una respuesta a la parte (3) de la pregunta (¿cómo consigo que la variable de entorno se importe en el escritorio de Unity?) En askubuntu . La sugerencia es crear un archivo ~ / .xsessionrc que será obtenido por / etc / X11 / Xsession. (He probado esto, y parece funcionar ... ¡sí!)

Todavía estoy perplejo por qué hacer para (4). Seguramente, si creo un trabajo cron (o demonio), puedo reemplazar '/ bin / foo' con algo como 'bash -i -c / bin / foo' para obligarlo a usar bash para cargar las variables de entorno correctas, pero Esto también significa que tendré que jugar con cualquier herramienta de terceros que pueda instalar tareas de daemon o trabajo cron en mi nombre. Yuk

Mickalot
fuente