Estoy buscando una forma simple y confiable de obtener el nombre del shell actual desde un script o un archivo de origen ( no desde la línea de comandos). Hubiera esperado hacerlo, $(basename "$SHELL")
pero si mi shell de inicio de sesión es zsh
y tengo el siguiente código en some_script.sh
this_shell=$( basename "$SHELL" )
echo "The Shell is $this_shell"
echo "The Shell is $0"
y lo ejecuto bash some_script.sh
, todavía aparece en zsh
lugar de bash
aunque el intérprete utilizado sea /bin/bash
. No estoy seguro de por qué los diseñadores de shell eligieron mostrar el shell predeterminado en lugar del shell actual, pero eso parece ser a lo que nos hemos quedado atrapados.
Hay algunas otras preguntas ligeramente similares ( aquí y aquí ), pero sus respuestas se quedan cortas de muchas maneras.
- A menudo asumen que el usuario está tratando de descubrir qué shell interactivo están usando actualmente, pero eso es una locura. Yo sé lo que estoy shell comandos de escritura en - Necesito código que se puede ejecutar en cualquier lugar para ser capaz de determinar qué shell se está utilizando.
- A menudo dan varias cosas diferentes para probar, nuevamente como si estuvieras en la línea de comando y solo puedes jugar hasta que aprendas que estás usando bash, pero necesito una sola cosa que sea confiable en todos los contextos.
- A menudo dan cosas que son completamente inútiles de los scripts, como
echo $0
. Eso falla como se muestra en el script anterior. (Sí, funciona en una línea de comandos de shell interactiva, pero ¿por qué no sabes qué shell estás usando?) - A veces dan comandos que (en mis pruebas limitadas) incluyen la información correcta, como
ps -p $$
, pero carecen de comandos sed / awk multiplataforma compatibles con shell cruzado para canalizarlo y obtener solo el nombre del shell e ignorar la otra información que aparece para el viaje. - Incluyen cosas que solo funcionarán en un par de conchas, como
$BASH_VERSION
y$ZSH_VERSION
. Quiero apoyar a la mayor cantidad posible de proyectiles, tales comofish
,csh
,tcsh
.
¿Cómo detecto de manera confiable y precisa cualquier shell actual ? Estoy buscando algo que funcione en todas las plataformas, en scripts y para la mayor cantidad de shells posibles y razonables 1 .
ACTUALIZACIÓN : Cuando publiqué esta pregunta, esperaba que hubiera alguna instalación integrada en los shells para darnos esta información, lo que parece no ser el caso. Dado que parece inevitable ahora confiar en algo fuera de los shells, debería hacer más explícito que estoy pidiendo unasolución multiplataforma (que, aunque implícito en mis objeciones a otras respuestas anteriores, podría ser fácil pasar por alto si no lo hace No leas la pregunta con cuidado).
Actualización 2 Si alguien todavía cree que este es un duplicado de la pregunta solo para Linux porque la respuesta de Stéphane no es solo para Linux, aquí están las diferencias entre lo que estoy pidiendo y lo que me ha proporcionado. (Tenga en cuenta que lo que ha escrito es ingenioso, y no lo estoy golpeando, pero no resuelve mi problema).
- Estoy buscando algo simple y confiable , que
- se puede agregar a cualquier secuencia de comandos o definición de función (que sería originada por un
.zshrc
o.bash_profile
o lo que sea) en rama. - No puede utilizar su secuencia de comandos como una utilidad externa que pasa el nombre del intérprete a la secuencia de comandos / función que realiza la llamada, ya que siempre será interpretada por el intérprete predeterminado y la devolverá. Esto hace que sea difícil o imposible de usar para mis propósitos. Si es posible, todavía es muy muy difícil, y la solución para hacerlo funcionar no se da en la respuesta. Por lo tanto, no respondió a mi pregunta, por lo tanto, no es un duplicado.
Si quieres ver algo que va a trabajar, echar un vistazo a ShellDetective en GitHub . Eso puede hacer que sea más fácil ver las diferencias entre lo que ya está presente en SE y lo que está buscando esta pregunta (y de hecho fue escrita para satisfacer las necesidades de esta pregunta, que no se habían satisfecho en ningún otro lugar).
(PS si no se puede creer que hay un caso de uso para esto, imagínese las funciones que se sourced en .zshrc
, .bash_profile
o .profile
dependiendo de lo que se está utilizando y qué servidor conchas que tiene disponibles. Están origen lo que no tienen línea de tinglado. Ellos son más útiles si pueden funcionar en cualquier shell, pero a veces tienen que saber en qué shell están para saber cómo comportarse).
1 No me interesan las "conchas" que no son conchas en ningún sentido tradicional de la palabra. No estoy preocupado por un caparazón que algún tipo escribió para sí mismo. Solo me preocupan los shells reales que realmente ocurren en la naturaleza, y que alguien podría tener que usar al iniciar sesión en un servidor en el que no pueden simplemente instalar los shells que quieran.
sh -c "…"
, y luego haga la mayor parte del trabajo en la sintaxis de shell POSIX.fish
para ejecutar tu script, ¿quieresfish
ocsh
?Respuestas:
He tenido excelentes resultados con esta combinación:
En Tru64 (OSF / 1), la salida tiene paréntesis alrededor del shell. Tachuela
tr -d '()'
para eliminarlos.Parece funcionar en todos los shells, en Solaris 10 y RHEL 5.7 / 6.4. No probé otras distribuciones como Debian, Ubuntu o Mint, pero creo que todas deberían funcionar igual; Tampoco tengo idea si FreeBSD funcionaría.
fuente
Así que todavía estoy tratando de desarrollar esto, pero creo que tengo una idea que funcionará. Como ha notado, lo que está tratando de hacer es, si no imposible, extremadamente difícil de hacer en todos los shells (cada variante que agregue al políglota aumenta la complejidad a una velocidad mayor que la lineal). probablemente podría hacerlo si se divide en Bourne (sh, ash, dash, bash, ksh, pdksh, zsh, etc.) y c shells de estilo (csh, tcsh, fish, etc.) pero la variación entre
csh
variantes presenta varias interesantes desafíosAsí que hagamos trampa y escribamos nuestra rutina de detección en un lenguaje conocido (bash con una línea shebang, C, perl, python, lo que sea) y determinemos el nombre del ejecutable del padre. entonces podemos usar dos trucos para devolver la información al padre, a saber, los valores de retorno y una sola palabra escrita en estándar. En sh shells descendientes, devolveríamos 0 y escribiríamos el nombre del shell ya que todos tienen un buen manejo de backtick. En la familia C de los shells podemos comenzar a incrementar el valor de retorno para cada conjunto de incompatibilidades que necesitamos solucionar. Los valores de retorno superiores a doscientos indicarían que los errores que comienzan con todo parecen estar bien, pero no puedo decir quién es mi padre en doscientos.
El programa interno parece fácil en Linux (
/proc/ppid/exe
es la mitad de la batalla). Estoy bastante seguro de que esto se puede hacer en bsd con opciones ps, pero no tengo un sistema bsd en ejecución en este momento para probar, y mi mac necesita un nuevo disco duro (y de todos modos es solo 10.4). Aunque reduce significativamente los problemas de sintaxis del shell, introduce un conjunto diferente de problemas de compatibilidad. Sigo pensando que tiene posibilidades.fuente
sh -c "..."
, que tomó de otra pregunta . (Lo siento: me salteé tu respuesta al principio porque no vi ningún código en ella y solo volví y la leí más tarde)case $shell in sh)...
(esa es la sintaxis exclusiva de Bourne) oswitch ($shell)
(solo csh).test "$shell" = "sh" && do-something
funciona encsh
/sh
/rc
/es
, pero nofish
.../dev/null
. Pero tengo una solución, que publicaré una vez que lo tenga todo funcionando.prueba algo como esto
fuente
csh
ytcsh
.fish
, pero entonces sólo enfish
, por desgracia:ps h -p %self -o args='' | cut -f1 -d' '
. Esto crea un problema de huevo y gallina ... debes saber que estásfish
en orden para ejecutar lafish
versión del código ...set shell_bin=`ps -p $$ -o args='' | cut -f1 -d' '`
- funcionará con CSH pero no con los demáscsh
/tcsh
, fue esta parte:ps -p $$ -o args='' | cut -f1 -d' '
que los rendimientos-sh
encsh
, y-csh
entcsh
.Creo que no siempre puedes obtener el nombre actual del shell , y creo que debe tener en cuenta las limitaciones de lo que es posible.
En las distribuciones de Linux, la mayoría de los usuarios tendrían
bash
como inicio de sesión y shell interactivo (ya quebash
es el shell predeterminado en la mayoría de las distribuciones). Algunos usuarios podrían establecer su concha azsh
,csh
(y variantes) o parafish
.(Como otros comentarios y respuestas explican, la búsqueda de forma fiable la cáscara de
bash
,zsh
,tcsh
,fish
que ya es un reto)Sin embargo, algunos usuarios extraños pueden configurar la shell de acceso a algo totalmente diferente - un intérprete de Lisp,
scsh
,es
, algún lenguaje de programación a la pitón, o Ocaml, o Perl, etc ...- y es su libertad para hacerlo. Probablemente, algunas personas están codificando su propio shell y usándolo de manera interactiva. Incluso si encuentra su extraño shell, no podrá hacer nada útil (por lo tanto, creo que no debería intentar obtener el nombre del shell).Así que supongo que está codificando algún archivo fuente (quizás generando uno) para configurar algún software. Así que solo explique lo que está haciendo y codifique para el caso común de
bash
(y tal vezzsh
&tcsh
) ...fuente
use a continuación bajo su propia responsabilidad exención de responsabilidad
fuente
-f
opción esté activadareadlink
, algunas implementaciones no tienen ese interruptor-f
como una opción disponible, tomando elformat
como argumento.readlink
no funciona en mi vm puredarwin, así que no tengo idea de lo que está sucediendo allí.