¿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_profilearchivo 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 icará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.bashdeshabilita 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 (aunqueyashtambién se establecePS1en 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
PS1del shell en la cadena de solicitud predeterminada. Entonces, si el shell es interactivo,PS1está configurado (a menos que el usuario lo.bashrchaya 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
PS1cuando 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 lovaresPS1?). Pero todas las versiones de bash hasta 4.4 (incluida la última versión que escribo) hacen esto.Muchos sistemas exportan
PS1al medio ambiente. Es una mala idea, porque se usan muchos shells diferentesPS1pero 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 quePS1esté configurado no sea un indicador confiable de que el shell sea interactivo. El shell podría haber heredadoPS1del entorno.Por qué se usa (mal) aquí
.bashrces el archivo que bash lee en el inicio cuando es interactivo. Un hecho menos conocido es que bash también lee.bashrces 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 esrshdosshd). En este segundo caso, es poco probable quePS1se 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_profileen ese shell. Pero.bash_profilees 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_profileen un shell sin inicio de sesión es perjudicial..bash_profile. Pero este es el caso en el que la carga.bash_profilepodría ser útil, ya que un intérprete de ingreso no interactivo no se carga automáticamente/etc/profiley~/.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_profilelugar de hacerlo.profile. La mayoría de los mecanismos de inicio de sesión de la GUI invocan.profilepero no.bash_profile(la lectura.bash_profilerequerirí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.profilelugar de.bash_profileestablecer variables de entorno. Agregar un puente entre.bashrcy.bash_profilecrea 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
-iestá habilitada.Esto es útil
.bashrcpara leer.profilesolo si el shell no es interactivo , es decir, lo contrario de lo que hace el código. Lea.profilesi 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)PS1si 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$PS1establecido en los archivos de inicio de bash (no imprimirá la cadena "cuco").$-contengaiun 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
bashno comenzó como un clon de shell POSIX sino como unBourne Shellclon.Como resultado, el comportamiento interactivo POSIX (
$ENVse llama para shells interactivos) se ha agregado más tardebashy no se conoce ampliamente.Hay un shell que garantiza un comportamiento similar. Esto es
cshy csh otorga que$prompttiene 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 -ifuncione, ni que$-contenga unipara shells interactivos. POSIX solo requiere quesh -iaplique el shell al modo interactivo.Dado que la variable
$PS1se puede importar desde el entorno, puede tener un valor incluso en modo no interactivo. El hecho de quebashunsetsPS1en 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/profileen 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.bashrcen 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/.bashrces 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,~/.profiley 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~/.profilepara la mayoría de los shells y~/.bashrc(casi equivalente a~/.bash_profile), específico solo para bash.Por tanto, es erróneo fuente
~/.bashrcen~/.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
.bashrcsi 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
~/.profileen~/.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
~/.bashrccarga, 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