¿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 .
¿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 .
Respuestas:
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).
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 (aunque yash
también se establece PS1
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!
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).
Un shell interactivo establece la variablePS1
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 lo var
es PS1
?). 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 diferentes PS1
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 que PS1
esté configurado no sea un indicador confiable de que el shell sea interactivo. El shell podría haber heredado PS1
del entorno.
.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 es rshd
o sshd
). En este segundo caso, es poco probable que PS1
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.
Hay una forma sencilla y portátil de probar si el shell actual es interactivo: pruebe si la opción -i
está habilitada.
case $- in
*i*) echo "This shell is interactive";;
*) echo "This shell is not interactive";;
esac
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.
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
[[ -o interactive ]]
(ksh, bash, zsh) o case $- 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, mientras PS1=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").
$-
contenga i
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 un Bourne Shell
clon.
Como resultado, el comportamiento interactivo POSIX ( $ENV
se llama para shells interactivos) se ha agregado más tarde bash
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:
$prompt not set non-interactive shell, test $?prompt.
$prompt set but == "" .cshrc called by the which(1) command.
$prompt set and != "" normal interactive shell.
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:
$ENV
que tiene un nombre específico de shell. Es por ejemplo
$HOME/.kshrc for the korn shell
$HOME/.bashrc for bash
$HOME/.mkshrc for mksh
$HOME/.shrc for the POSIX Bourne Shell
Otras personas mencionaron la bandera de shell -i
, pero esto no es utilizable para una programación confiable. POSIX no requiere que set -i
funcione, ni que $-
contenga un i
para shells interactivos. POSIX solo requiere que sh -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 que bash
unset
s PS1
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
.
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,
Solo para averiguar si el shell es interactivo.
El valor predeterminado /etc/profile
en debian y ubuntu (desde / usr / share / base-files / profile):
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
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:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
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 $-
):
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Eso debería mostrar claramente el por qué de PS1 y una alternativa.
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 :
# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
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.
( 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.