Estou procurando uma maneira simples e confiável de obter o nome do shell atual de dentro de um script ou arquivo ( não da linha de comando). Eu esperava apenas fazer isso, $(basename "$SHELL")
mas se meu shell de login for zsh
e eu tenho o seguinte código em some_script.sh
this_shell=$( basename "$SHELL" )
echo "The Shell is $this_shell"
echo "The Shell is $0"
e eu corro com ele bash some_script.sh
, ele ainda lista, em zsh
vez de bash
ser o intérprete usado /bin/bash
. Não sei por que os designers de shell escolheram mostrar o shell padrão em vez do shell atual, mas parece que é com isso que estamos presos.
Existem outras perguntas um pouco semelhantes ( aqui e aqui ), mas suas respostas são insuficientes de várias maneiras.
- Eles geralmente assumem que o usuário está tentando descobrir qual shell interativo está usando atualmente, mas isso é loucura. Eu sei em qual shell estou digitando comandos - preciso de um código que possa ser executado em qualquer lugar para determinar qual shell ele está usando.
- Eles geralmente oferecem várias coisas diferentes para tentar - novamente, como se você estivesse na linha de comando e pode apenas mexer até aprender que está usando o bash - mas eu preciso de uma coisa única que seja confiável em todos os contextos.
- Eles geralmente dão coisas que são totalmente inúteis nos scripts, como
echo $0
. Isso falha, como mostrado no script acima. (Sim, ele funciona em uma linha de comando do shell interativo, mas por que você nunca sabe qual shell está usando?) - Às vezes, eles dão comandos que (nos meus testes limitados) incluem as informações corretas, como
ps -p $$
, mas não possuem comandos sed / awk compatíveis com várias plataformas e vários shell para canalizá-lo para obter apenas o nome do shell e ignorar as outras informações que aparecem para o passeio. - Eles incluem coisas que só funcionam em algumas conchas, como
$BASH_VERSION
e$ZSH_VERSION
. Quero apoiar como muitas conchas quanto possível, tais comofish
,csh
,tcsh
.
Como detecto de maneira confiável e precisa qualquer shell atual ? Estou procurando por algo que funcione em várias plataformas, em scripts e no maior número possível de shells possíveis e razoáveis 1 .
ATUALIZAÇÃO : Quando postei essa pergunta, esperava que houvesse alguma facilidade embutida nas conchas para nos fornecer essas informações, o que parece não ser o caso. Como agora parece inevitável contar com algo fora dos escudos, devo deixar mais explícito que estou pedindo umasolução de plataforma cruzada (que, embora implícita pelas minhas objeções a outras respostas acima, pode ser fácil perder se você não leia a pergunta com atenção).
Atualização 2 Se alguém ainda acredita que essa é uma duplicata da pergunta somente sobre Linux, porque a resposta de Stéphane não é somente Linux, eis as diferenças entre o que estou pedindo e o que ele forneceu. (Observe que o que ele escreveu é engenhoso, e eu não estou brincando, mas isso não resolve o meu problema.)
- Estou procurando por algo simples e confiável , que
- pode ser adicionado a qualquer definição de script ou função (que seriam originados por um
.zshrc
ou.bash_profile
ou qualquer outro) em galho. - Você não pode usar o script dele como um utilitário externo que passa o nome do intérprete para o script / função de chamada, pois ele sempre será interpretado pelo intérprete padrão e retornará isso. Isso torna difícil ou impossível de usar para meus propósitos. Se possível, ainda é muito, muito difícil, e a solução para fazê-lo funcionar não é dada na resposta. Portanto, ele não respondeu à minha pergunta, portanto, não é uma duplicata.
Se você quiser ver algo que vai funcionar, dê uma olhada ShellDetective no GitHub . Isso pode facilitar a visualização das diferenças entre o que já está presente no SE e o que esta pergunta está procurando (e de fato foi escrita para satisfazer as necessidades dessa questão, que não foram atendidas em nenhum outro lugar).
(PS se você não pode acreditar que há um caso de uso para isso, imagine funções que são de origem em .zshrc
, .bash_profile
ou .profile
dependendo de qual servidor está sendo usado e que conchas que tem disponível. Eles estão de origem para que eles não têm nenhuma linha shebang. Eles são mais úteis se puderem funcionar em qualquer shell, mas às vezes eles precisam saber em qual shell estão para saber como se comportar.)
1 Não estou preocupado com "conchas" que não sejam conchas no sentido tradicional da palavra. Eu não estou preocupado com alguma concha que um cara escreveu para si mesmo. Estou preocupado apenas com os shells reais que realmente ocorrem na natureza e que alguém pode ter que usar ao fazer login em algum servidor no qual eles não podem simplesmente instalar os shells que quiserem.
sh -c "…"
e faça a maior parte do trabalho na sintaxe do shell POSIX.fish
e use-a para executar seu script, desejafish
oucsh
?Respostas:
Eu tive ótimos resultados com essa combinação:
No Tru64 (OSF / 1), a saída tem parênteses em torno do shell. Prenda
tr -d '()'
para removê-los.Aparece para trabalhos em todos os shells, no Solaris 10 e RHEL 5.7 / 6.4. Não testou outras distribuições, como Debian, Ubuntu ou Mint, mas acho que todas deveriam funcionar da mesma maneira; Eu também não tenho idéia se o FreeBSD funcionaria.
fonte
Então, ainda estou tentando explicar isso, mas acho que tenho uma ideia que funcionará. Como você notou, o que você está tentando fazer é, se não impossível, extremamente difícil de fazer em todas as conchas (cada variante adicionada ao poliglota aumenta a complexidade a uma taxa maior que a linear). você provavelmente poderia fazê-lo se se dividir em Bourne (sh, ash, dash, bash, ksh, pdksh, zsh etc.) e conchas no estilo c (csh, tcsh, fish, etc.), mas a variação entre as
csh
variantes apresenta vários recursos interessantes desafios.Então, vamos trapacear e escrever nossa rotina de detecção em uma linguagem conhecida (bash com uma linha shebang, C, perl, python, qualquer que seja) e determinar o nome do executável do pai. podemos então usar dois truques para obter as informações de volta aos pais, ou seja, retornar valor (es) e uma única palavra escrita como padrão. Em sh descendentes, retornaríamos 0 e escreveríamos o nome do shell, pois todos eles têm um bom manuseio de backtick. na família C de shells, podemos começar a incrementar o valor de retorno para cada conjunto de incompatibilidades que precisamos solucionar. Valores de retorno acima de duzentos indicariam erros começando com tudo, mas tudo bem, mas não sei dizer quem é meu pai aos duzentos.
O programa interno parece fácil no linux (
/proc/ppid/exe
é metade da batalha). Tenho certeza de que isso pode ser feito no bsd com as opções ps, mas não tenho um sistema bsd em execução no momento para testar, e meu mac precisa de um novo disco rígido (e é apenas 10,4 de qualquer maneira). Embora reduza significativamente os problemas de sintaxe do shell, ele apresenta um conjunto diferente de problemas de compatibilidade. Eu ainda acho que tem possibilidades.fonte
sh -c "..."
qual ele tirou outra pergunta . (Desculpe: Eu saltei sua resposta no início porque eu não vi nenhum código nele, e só voltou e lê-lo mais tarde.)case $shell in sh)...
(que é sintaxe apenas Bourne) ouswitch ($shell)
(apenas csh).test "$shell" = "sh" && do-something
trabalha emcsh
/sh
/rc
/es
, mas nãofish
.../dev/null
. Mas tenho uma solução, que vou postar assim que estiver tudo funcionando.tente algo assim
fonte
csh
etcsh
.fish
, mas, em seguida, apenas emfish
, infelizmente:ps h -p %self -o args='' | cut -f1 -d' '
. Isso cria um problema galinha e do ovo ... você tem que saber que você está emfish
, a fim de executar afish
versão do código ...set shell_bin=`ps -p $$ -o args='' | cut -f1 -d' '`
- irá trabalhar com CSH, mas não os outroscsh
/tcsh
, foi esta parte:ps -p $$ -o args='' | cut -f1 -d' '
, que retorna-sh
emcsh
, e-csh
emtcsh
.Eu acredito que você nem sempre pode obter o nome do shell atual e acho que você deve estar ciente das limitações do que é possível.
Nas distribuições Linux, a maioria dos usuários teria
bash
como logon e shell interativo (já quebash
é o shell padrão na maioria das distribuições). Alguns usuários que definiu seu shell parazsh
,csh
(e variantes) ou parafish
.(Como outros comentários e respostas explicar, encontrar confiável a casca fora de
bash
,zsh
,tcsh
,fish
já é um desafio)Mas alguns usuários estranhos pode definir a sua shell de login para algo totalmente diferente - um interpretador Lisp,
scsh
,es
, alguma linguagem de script à la Python, ou Ocaml, ou Perl, etc ...- e é sua liberdade para fazê-lo. Provavelmente, algumas pessoas estão codificando seu próprio shell e usando-o de forma interativa. Mesmo que você tenha encontrado o shell estranho, não poderá fazer nada útil (por isso acredito que você não deve tentar obter o nome do shell).Então eu acho que você está codificando algum arquivo fonte (talvez gerando um) para configurar algum software. Então, apenas explique o que você está fazendo e codifique o caso comum de
bash
(e talvezzsh
&tcsh
) ....fonte
use abaixo por sua conta e risco
fonte
-f
opção noreadlink
, algumas implementações não tem esse interruptor-f
como uma opção disponível, considerando-aformat
como argumento.readlink
não trabalhando no meu puredarwin vm, então não faço ideia do que está acontecendo lá.