¿Para qué sirve el [ -n "$PS1" ]
en [ -n "$PS1" ] && source ~/.bash_profile;
? Esta línea se incluye en un repositorio de.bashrc
archivos de puntos .
10
¿Para qué sirve el [ -n "$PS1" ]
en [ -n "$PS1" ] && source ~/.bash_profile;
? Esta línea se incluye en un repositorio de.bashrc
archivos de puntos .
Esto verifica si el shell es interactivo o no. En este caso, solo obtiene el ~/.bash_profile
archivo si el shell es interactivo.
Consulte "¿Es este Shell interactivo?" en el manual de bash, que cita ese idioma específico. (También recomienda verificar si el shell es interactivo probando si la $-
variable especial contiene el i
carácter, que es un mejor enfoque para este problema).
( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )
, que simplemente imprime[]
. Parece que zsh no hace lo mismo, al menos desde un experimento ... En cualquier caso, la intención del[ -n "$PS1" ]
es verificar si el shell es interactivo o no.bash
deshabilita PS1 cuando no es interactivo (error tipográfico en su comentario anterior) es un error de la OMI, PS1 no es una variable específica de bash, no tiene nada que desarmarlo. Es el único shell que hace eso (aunqueyash
también se establecePS1
en un valor predeterminado incluso cuando no es interactivo).[[ $- = *i* ]] && source ~/.bash_profile
).[ -n "${PS1}" ]
, pero todavía he actualizado mi respuesta para resaltar que el manual de bash también sugiere / recomienda inspeccionar$-
para determinar si el shell es interactivo, espero que encuentre que mejora la respuesta. ¡Salud!Que hace esto
Esta es una forma generalizada de probar si el shell es interactivo. Tenga en cuenta que solo funciona en bash, no funciona con otros shells. Por lo tanto, está bien (si es tonto)
.bashrc
, pero no funcionaría.profile
(lo que lee sh, y bash es solo una de las implementaciones posibles de sh, y no la más común).Por qué funciona (¡solo en bash!)
Un shell interactivo establece la variable
PS1
del shell en la cadena de solicitud predeterminada. Entonces, si el shell es interactivo,PS1
está configurado (a menos que el usuario lo.bashrc
haya eliminado, lo que no puede haber sucedido todavía en la parte superior.bashrc
, y podría considerar que es algo tonto de todos modos).Lo contrario es cierto en bash: las instancias no interactivas de bash se desarman
PS1
cuando comienzan. Tenga en cuenta que este comportamiento es específico de bash, y podría decirse que es un error (¿por québash -c '… do stuff with $var…'
no funcionaría cuando lovar
esPS1
?). Pero todas las versiones de bash hasta 4.4 (incluida la última versión que escribo) hacen esto.Muchos sistemas exportan
PS1
al medio ambiente. Es una mala idea, porque se usan muchos shells diferentesPS1
pero con una sintaxis diferente (por ejemplo, los escapes de prompt de bash son completamente diferentes de los escapes de prompt de zsh ). Pero está lo suficientemente extendido como para que, en la práctica, ver quePS1
esté configurado no sea un indicador confiable de que el shell sea interactivo. El shell podría haber heredadoPS1
del entorno.Por qué se usa (mal) aquí
.bashrc
es el archivo que bash lee en el inicio cuando es interactivo. Un hecho menos conocido es que bash también lee.bashrc
es un shell de inicio de sesión y la heurística de bash concluye que se trata de una sesión remota (bash comprueba si su padre esrshd
osshd
). En este segundo caso, es poco probable quePS1
se establezca en el entorno, porque todavía no se ha ejecutado ningún archivo de puntos.Sin embargo, la forma en que el código usa esta información es contraproducente.
.bash_profile
en ese shell. Pero.bash_profile
es un script de tiempo de inicio de sesión. Puede ejecutar algunos programas que están destinados a ejecutarse solo una vez por sesión. Podría anular algunas variables de entorno que el usuario había establecido deliberadamente en un valor diferente antes de ejecutar ese shell. Ejecutar.bash_profile
en un shell sin inicio de sesión es perjudicial..bash_profile
. Pero este es el caso en el que la carga.bash_profile
podría ser útil, ya que un intérprete de ingreso no interactivo no se carga automáticamente/etc/profile
y~/.profile
.Creo que la razón por la que las personas hacen esto es para los usuarios que inician sesión a través de una GUI (un caso muy común) y que establecen su configuración de variables de entorno en
.bash_profile
lugar de hacerlo.profile
. La mayoría de los mecanismos de inicio de sesión de la GUI invocan.profile
pero no.bash_profile
(la lectura.bash_profile
requeriría ejecutar bash como parte del inicio de sesión, en lugar de sh). Con esta configuración, cuando el usuario abre un terminal, obtendrá sus variables de entorno. Sin embargo, el usuario no obtendrá sus variables de entorno en las aplicaciones GUI, lo cual es una fuente muy común de confusión. La solución aquí es usar en.profile
lugar de.bash_profile
establecer variables de entorno. Agregar un puente entre.bashrc
y.bash_profile
crea más problemas de los que resuelve.Que hacer en su lugar
Hay una forma sencilla y portátil de probar si el shell actual es interactivo: pruebe si la opción
-i
está habilitada.Esto es útil
.bashrc
para leer.profile
solo si el shell no es interactivo , es decir, lo contrario de lo que hace el código. Lea.profile
si bash es un shell de inicio de sesión (no interactivo) y no lo lea si es un shell interactivo.fuente
[[ -o interactive ]]
(ksh, bash, zsh) ocase $- in (*i*) ...; esac
(POSIX)PS1
si no se ejecuta de forma interactiva. Es bastante fácil de probar:PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
no imprimirá nada, mientrasPS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
imprime el valor$PS1
establecido en los archivos de inicio de bash (no imprimirá la cadena "cuco").$-
contengai
un shell interactivo.[ -n "${PS1}" ]
mal es ir demasiado lejos, después de todo, solo se rompe cuando alguien está exportando PS1 (lo que en su respuesta dice que es una mala idea e incluso explica las razones) y eso no afecta bash de todos modos (ya que deshabilita PS1 y PS2 si el shell no es interactivo). Quizás hubiera sido mejor usar una palabra como "desanimado" o hablar sobre las "limitaciones" del enfoque. No creo que esté "mal" del todo. Si algo está mal es exportar PS1, ¡eso es seguro! De todos modos, gracias por entrar en los detalles de esto.Parece que este concepto extraño es el resultado del hecho de que
bash
no comenzó como un clon de shell POSIX sino como unBourne Shell
clon.Como resultado, el comportamiento interactivo POSIX (
$ENV
se llama para shells interactivos) se ha agregado más tardebash
y no se conoce ampliamente.Hay un shell que garantiza un comportamiento similar. Esto es
csh
y csh otorga que$prompt
tiene valores específicos:Pero esto no se aplica al Bourne Shell ni a los shells POSIX.
Para un shell POSIX, el único método otorgado es poner código para shells interactivos en el archivo:
que tiene un nombre específico de shell. Es por ejemplo
Otras personas mencionaron la bandera de shell
-i
, pero esto no es utilizable para una programación confiable. POSIX no requiere queset -i
funcione, ni que$-
contenga uni
para shells interactivos. POSIX solo requiere quesh -i
aplique el shell al modo interactivo.Dado que la variable
$PS1
se puede importar desde el entorno, puede tener un valor incluso en modo no interactivo. El hecho de quebash
unset
sPS1
en cualquier shell no interactivo no está garantizado por el estándar y no lo hace ningún otro shell.Entonces, la programación limpia (incluso con
bash
) consiste en poner los comandos para shells interactivos$HOME/.bashrc
.fuente
Primero voy a hablar de lo que Debian, y la mayoría de las veces también Ubuntu configura para bash. Y este último toque en otros sistemas.
En la configuración de los archivos de inicio de shell hay mucha opinión.
También tengo mi opinión, pero intentaré mostrar ejemplos existentes de configuraciones correctas.
Usaré debuan ya que es bastante fácil encontrar ejemplos de sus archivos.
Y debian se usa mucho, por lo que la configuración se ha probado bien,
¿Cuál es el objetivo de verificar que PS1 esté configurado?
Solo para averiguar si el shell es interactivo.
El valor predeterminado
/etc/profile
en debian y ubuntu (desde / usr / share / base-files / profile):Se lee el if: si es interactivo (conjunto predeterminado de PS1) y es un shell bash (pero no actúa como predeterminado
sh
), cambie PS1 a uno nuevo en particular (no el predeterminado).El valor predeterminado
/etc/bash.bashrc
en debian también contiene:Lo que está bastante claro en lo que hace: si es interactivo, no fuente (el resto).
Sin embargo, en
/etc/skel/.bashrc
es un ejemplo de la forma correcta de probar un shell interactivo (usando$-
):Eso debería mostrar claramente el por qué de PS1 y una alternativa.
El orden correcto
Se debe evitar la configuración que está informando.
La orden (de los ajustes del sistema a la configuración de usuario más específicos (para bash)) es
/etc/profile
,/etc/bash.bashrc
,~/.profile
y finalmente~/.bashrc
. Eso coloca los efectos más amplios (y para más shells) en/etc/profile
(que es propiedad de root) seguido de/etc/bash.bashrc
(que también es propiedad de root) pero solo afecta a bash. Luego vienen los ajustes personales$HOME
, el primero es~/.profile
para la mayoría de los shells y~/.bashrc
(casi equivalente a~/.bash_profile
), específico solo para bash.Por tanto, es erróneo fuente
~/.bashrc
en~/.profile
, se está transformando un escenario de fiesta de una manera más general que está determinado usuario afectando a más conchas . Excepto si se hace de esta manera :Comprueba que bash se está ejecutando y solo se carga
.bashrc
si ese es el caso.Esta es una decisión previa proveniente de Debian. La razón se explica aquí .
De hecho, a la inversa, el abastecimiento
~/.profile
en~/.bash_profile
(o~/.bashrc
) solo está volviendo a aplicar reglas generales que ya deberían haberse cargado a un caso de uso en particular, y por lo tanto "no está tan mal" (no digo "bueno"). Y no digo nada bueno porque puede hacer que el origen de los archivos se repita. Como cuando un subdirectorio carga un padre, ese es un bucle de directorio.Y es en este abastecimiento cruzado que la verificación de shell interactivo tiene sentido. Solo cuando un shell es interactivo se
~/.bashrc
carga, pero a su vez puede estar cargando~/.profile
(o al revés) y es en este caso que podría usarse la comprobación de un shell interactivo.fuente