Testar recursos específicos (por exemplo, !substitui?) É provavelmente mais portátil do que encontrar o nome do shell. Costume local pode ter você correndo algo chamado /bin/shque poderia realmente ser cinzas, traço, festança, etc.
msw
1
@ msw: Parece um bom comentário, exceto que me deixa pensando "como?".
#
Parece que não há uma resposta simples para esta pergunta. Se não pudermos consultar o shell, talvez a melhor abordagem seja sempre especificar o shell. Não tenho certeza de que isso sempre seja possível, mas talvez seja mais fácil do que as pessoas geralmente supõem.
@ Aniket, não ajuda tanto quanto você pensa - está interessado apenas em processos de shell interativos .
Toby Speight
Respostas:
794
Existem três abordagens para encontrar o nome do executável do shell atual:
Observe que todas as três abordagens podem ser enganadas se o executável do shell for /bin/sh, mas é realmente renomeado bash, por exemplo (o que geralmente acontece).
Assim, sua segunda pergunta sobre se a pssaída servirá é respondida com " nem sempre ".
echo $0 - imprimirá o nome do programa ... que, no caso do shell, é o shell real.
ps -ef | grep $$ | grep -v grep- isso procurará o ID do processo atual na lista de processos em execução. Como o processo atual é o shell, ele será incluído.
Isso não é 100% confiável, pois você pode ter outros processos cuja pslista inclui o mesmo número que o ID do processo do shell, especialmente se esse ID for um número pequeno (por exemplo, se o PID do shell for "5", você poderá encontrar processos chamados "java5" ou "perl5" na mesma grepsaída!). Este é o segundo problema com a abordagem "ps", além de não poder confiar no nome do shell.
echo $SHELL- O caminho para o shell atual é armazenado como a SHELLvariável para qualquer shell. A ressalva é que, se você iniciar um shell explicitamente como um subprocesso (por exemplo, não é o seu shell de login), obterá o valor do shell de login. Se for possível, use a abordagem psou $0.
Se, no entanto, o executável não corresponder ao seu shell real (por exemplo, /bin/shé realmente bash ou ksh), você precisará de heurísticas. Aqui estão algumas variáveis ambientais específicas para várias conchas:
$version está definido no tcsh
$BASH é definido no bash
$shell (minúsculo) é definido como o nome real do shell em csh ou tcsh
$ZSH_NAME está definido no zsh
O ksh possui $PS3e $PS4define, enquanto o shell Bourne normal ( sh) apenas possui $PS1e $PS2define. Isso geralmente parece ser o mais difícil de distinguir - a única diferença em todo o conjunto de variáveis de ambiente entre she kshtemos instalado no Solaris boxen é $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDS, e $TMOUT.
ps -p $$como Matthew Slattery aponta. Para ksh: echo $KSH_VERSIONou echo ${.sh.version}.
Pausado até novo aviso.
@ Dennish - meu ksh agora não tem KSH_VERSION definido. e echo ${.sh.version}retorna "Substituição incorreta". Veja minha solução acima
DVK
3
“ ps -ef | grep …… Isso não é 100% confiável como…” O uso de uma expressão regular simples via egrepou grep -epode facilmente trazer a confiabilidade até 100% para todos os efeitos - ps -ef | egrep "^\s*\d+\s+$$\s+". As ^marcas certeza de que estamos a partir do início da linha, os \d+come-se o UID, o $$corresponde ao PID, eo \s*e \s+conta para e garantir espaço em branco entre as outras partes.
Slipp D. Thompson
2
@ SlippD.Thompson não funcionou no GNU / Linux. Mas isso parece funcionar:ps -ef | awk '$2==pid' pid=$$
jarno
98
ps -p $$
deve funcionar em qualquer lugar que as soluções que envolvem ps -efe funcionem grep(em qualquer variante Unix que suporte opções POSIXps ) e não sofrerá com os falsos positivos introduzidos pelo grepping para uma sequência de dígitos que pode aparecer em outro lugar.
Alguns shells possuem sua própria versão interna, psque pode não ser entendida, -pportanto, você pode precisar usá-lo /bin/ps -p $$.
Pausado até novo aviso.
13
Todas as conchas que eu conheço entendem, $$exceto as fishque você precisaria usar ps -p %self.
Pausado até novo aviso.
3
Na verdade, você não deve confiar em caminhos difíceis como /bin/ps. pspoderia facilmente (atualmente é bastante normal hoje em dia) ser instalado no /usr/bin. $(which ps) -p $$é uma maneira melhor. Obviamente, isso não funcionará em peixes e, possivelmente, em outras conchas. Eu acho que é (which ps) -p %selfem peixe.
Aron Cederholm
1
Em alguns sistemas mínimos, como um container docker debian-slim, o ps pode não estar lá. Nesse caso, essa abordagem ainda funciona:readlink /proc/$$/exe
mxmlnkn 28/02/19
se o seu shfor emulado por bash, ps -p lhe dará /usr/bin/bashaté você executá-lo como #sh
Este é um bom curto. Eu estava me usando ps -o fname --no-headers $$.
Anne van Rossum
Obrigado. Achei essa a melhor opção para usar em um script para proteger comandos específicos do bash test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash. (A próxima linha no meu script tem o equivalente para csh.)
craq
1
Descobri que se você fizer isso de dentro de um subshell, isso pode levar a linhas extras falsas, combinando o PID do pai e o processo de shell real. Para isso, uso em -qvez de -p:SHELL=$(ps -ocomm= -q $$)
Steve
35
Se você apenas deseja garantir que o usuário esteja chamando um script com o Bash:
if[!-n "$BASH"];then echo Please run this script $0 with bash;exit1;fi
Este deve ser o mais próximo do topo. Muito obrigado.
Alex Skrypnyk
4
Não deve estar mais perto do topo, porque não responde à pergunta. Se a pergunta for "Como verificar se o script está sendo executado no bash", eu voto a favor.
David Ferenczy Rogožan 14/10
2
@DawidFerenczy - Essa pergunta é o resultado principal quando você procura essa frase. A longo prazo, acho muito mais importante que as respostas respondam ao que as pessoas estão procurando do que ao que se tratava a pergunta original.
ArtOfWarfare
3
Além disso, a variável $ BASH é definida em tcsh se o tcsh for chamado a partir do bash
18446744073709551615
Isso é muito útil, obrigado. Apenas adaptado um pouco, colocar isso como a segunda linha depois #!/bin/bash: if [ ! -n "$BASH" ] ;then exec bash $0; fi. Com esta linha, o script é executado usando o bash, mesmo que você comece a usar o ksh ou sh. Meu caso de uso não precisa de argumentos de linha de comando, mas eles podem ser adicionados depois, $0se necessário.
Qual é o ponto de grep seguido por awk, quando o /pattern/ { action }fará?
Jens
# no zshell alias shell = 'echo $ {SHELL: t}'
SergioAraujo 13/01
4
$SHELLA variável de ambiente contém um shell, que é configurado como padrão para um usuário atual. Ele não reflete um shell, que está sendo executado no momento. Também é melhor usar do ps -p $$que grepping $$ por causa de falsos positivos.
David Ferenczy Rogožan 14/10
O env $ SHELL. A variável aponta para o shell 'pai', conforme especificado na especificação POSIX: SHELL Essa variável deve representar um nome de caminho do interpretador de linguagem de comando preferido do usuário. Portanto, o valor de $ SHELL pode não ser o shell atual.
$SHELLnem sempre é necessário mostrar o shell atual. Ele reflete apenas o shell padrão a ser chamado.
Para testar o que bashfoi dito acima, digamos que é o shell padrão, tente echo $SHELLe, no mesmo terminal, entre em outro shell ( KornShell (ksh), por exemplo) e tente $SHELL. Você verá o resultado como bash nos dois casos.
Para obter o nome do shell atual, use cat /proc/$$/cmdline. E o caminho para o shell executável por readlink /proc/$$/exe.
ps é o método mais confiável. Não é garantido que a variável de ambiente SHELL seja configurada e, mesmo que seja, ela pode ser facilmente falsificada.
+1 $ SHELL é o shell padrão para programas que precisam gerar um. Não reflete necessariamente o shell que está sendo executado no momento.
Jim Lewis
8
Eu tenho um truque simples para encontrar o shell atual. Basta digitar uma sequência aleatória (que não é um comando). Ele falhará e retornará um erro "não encontrado", mas no início da linha, ele dirá qual shell é:
ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
Não é bom em um script. echo 'aaaa' > script; chmod +x script; ./scriptdá./script.sh: 1: aaaa: not found
slim
6
O seguinte sempre fornecerá o shell real usado - ele obtém o nome do executável real e não o nome do shell (por exemplo, em ksh93vez de kshetc.). Pois /bin/sh, mostrará o shell atual usado, ie dash.
ls -l /proc/$$/exe | sed 's%.*/%%'
Sei que muitos dizem que a lssaída nunca deve ser processada, mas qual é a probabilidade de você usar um shell nomeado com caracteres especiais ou colocado em um diretório nomeado com caracteres especiais? Se esse ainda for o caso, há muitos outros exemplos de como fazê-lo de maneira diferente.
Conforme apontado por Toby Speight , essa seria uma maneira mais adequada e mais limpa de conseguir o mesmo:
Isso apenas erros em todos os Unices que não fornecem /proc. Nem todo mundo é um Linux.
Jens
5
E se você está no Linux, nós preferimos basename $(readlink /proc/$$/exe)a ls+ sed+ echo.
precisa saber é o seguinte
1
Isso fornecerá o nome do executável real , não o shell real . Quando o shell real é vinculado como um applet do busybox, digamos ash -> /bin/busybox, isso fornecerá / bin / busybox.
stepse
6
Eu tentei muitas abordagens diferentes e a melhor para mim é:
ps -p $$
Também funciona com Cygwin e não pode produzir falsos positivos como grepping de PID. Com alguma limpeza, ele gera apenas um nome executável (em Cygwin com path):
ps -p $$ | tail -1| awk '{print $NF}'
Você pode criar uma função para não precisar memorizá-la:
# Print currently active shell
shell (){
ps -p $$ | tail -1| awk '{print $NF}'}
Na minha configuração (Cygwin | Windows 7), sua resposta é a melhor e ps -p $$ | cauda -1 | O gawk '{print $ NF}' funciona mesmo a partir do cmd sem o $ bash. Observe gawk em vez de awk, pois o awk funciona apenas no bash.
WebComer
@WebComer Desculpe, não sei ao certo o que você quer dizer com " funciona mesmo no cmd sem o $ bash ". Mesmo se você tiver portas Windows de ps, taile gawk, cmd não define $$como PID, então definitivamente não pode funcionar sob o cmd comum.
David Ferenczy Rogožan 11/03/19
Por que não simplesmente ps -p$$ -o comm=? O POSIX diz que especificar todos os cabeçalhos vazios suprime completamente o cabeçalho. Ainda estamos falhando (como todas as psrespostas) quando somos originados por um script executado diretamente (por exemplo #!/bin/sh).
Toby Speight
5
Minha variante na impressão do processo pai:
ps -p $$ | awk '$1 == PP {print $4}' PP=$$
Não execute aplicativos desnecessários quando o AWK puder fazer isso por você.
Por que executar um desnecessário awk, quando ps -p "$$" -o 'comm='pode fazer isso por você?
Toby Speight
5
Existem muitas maneiras de descobrir o shell e sua versão correspondente. Aqui estão alguns que funcionaram para mim.
Direto
$> echo $ 0 (fornece o nome do programa. No meu caso, a saída era -bash .)
$> $ SHELL (Isso leva você para o shell e, no prompt, você obtém o nome e a versão do shell. No meu caso, bash3.2 $ .)
$> echo $ SHELL (Isso fornecerá um caminho executável. No meu caso / bin / bash .)
$> $ SHELL --version (Isso fornecerá informações completas sobre o software shell com o tipo de licença)
Abordagem Hackish
$> ******* (Digite um conjunto de caracteres aleatórios e, na saída, você obterá o nome do shell. No meu caso -bash: chapter2-a-sample-isomorphic-app: comando não encontrado )
Desde que você /bin/shsuporte o padrão POSIX e seu sistema possua o lsofcomando instalado - uma possível alternativa possível lsofneste caso pid2path- você também pode usar (ou adaptar) o seguinte script que imprime caminhos completos:
#!/bin/sh# cat /usr/local/bin/curshset-eu
pid="$$"set-- sh bash zsh ksh ash dash csh tcsh pdksh mksh fish psh rc scsh bournesh wish Wish login
unset echo env sed ps lsof awk getconf
# getconf _POSIX_VERSION # reliable test for availability of POSIX system?
PATH="`PATH=/usr/bin:/bin:/usr/sbin:/sbin getconf PATH`"[ $?-ne 0]&&{ echo "'getconf PATH' failed";exit1;}export PATH
cmd="lsof"
env -i PATH="${PATH}" type "$cmd"1>/dev/null2>&1||{ echo "$cmd not found";exit1;}
awkstr="`echo "$@" | sed 's/\([^ ]\{1,\}\)/|\/\1/g; s/ /$/g' | sed 's/^|//; s/$/$/'`"
ppid="`env -i PATH="${PATH}" ps -p $pid -o ppid=`"["${ppid}"X =""X ]&&{ echo "no ppid found";exit1;}
lsofstr="`lsof -p $ppid`"||{ printf "%s\n""lsof failed""try: sudo lsof -p \`ps -p \$\$ -o ppid=\`";exit1;}
printf "%s\n""${lsofstr}"|
LC_ALL=C awk -v var="${awkstr}"'$NF ~ var {print $NF}'
isso funciona em peixes! mas, para mim, falha no bash, devido à opção -i(-> ignore environment) envna linha em que você verifica a lsofdisponibilidade. ele falha com: env -i PATH="${PATH}" type lsof->env: ‘type’: No such file or directory
hoijui 14/03
2
Se você quiser apenas verificar se está executando (uma versão específica do) Bash, a melhor maneira de fazer isso é usar a $BASH_VERSINFOvariável de matriz. Como uma variável de matriz (somente leitura), ela não pode ser definida no ambiente, portanto, você pode ter certeza de que está vindo (se houver) do shell atual.
No entanto, como o Bash tem um comportamento diferente quando chamado como sh, você também precisa verificar a $BASHvariável de ambiente que termina com /bash.
Em um script que escrevi que usa nomes de funções com -(sem sublinhado) e depende de matrizes associativas (adicionadas no Bash 4), tenho a seguinte verificação de integridade (com mensagem de erro útil do usuário):
case`eval 'echo $BASH@${BASH_VERSINFO[0]}' 2>/dev/null`in*/bash@[456789])# Claims bash version 4+, check for func-names and associative arraysif!eval"declare -A _ARRAY && func-name() { :; }"2>/dev/null;then
echo >&2"bash $BASH_VERSION is not supported (not really bash?)"exit1fi;;*/bash@[123])
echo >&2"bash $BASH_VERSION is not supported (version 4+ required)"exit1;;*)
echo >&2"This script requires BASH (version 4+) - not regular sh"
echo >&2"Re-run as \"bash $CMD\" for proper operation"exit1;;esac
Você pode omitir a verificação funcional um tanto paranóica de recursos no primeiro caso e apenas assumir que versões futuras do Bash seriam compatíveis.
Nenhuma das respostas funcionou com o fishshell (ele não possui as variáveis $$ou $0).
Isso funciona para mim (testadas sh, bash, fish, ksh, csh, true, tcsh, e zsh; openSUSE 13.2):
ps | tail -n 4| sed -E '2,$d;s/.* (.*)/\1/'
Este comando gera uma string como bash. Aqui eu só estou usando ps, taile sed(sem extesions GNU; tentar adicionar --posixpara verificá-lo). Todos eles são comandos POSIX padrão. Tenho certeza que tailpode ser removido, mas meu sedfu não é forte o suficiente para fazer isso.
Parece-me que esta solução não é muito portátil, pois não funciona no OS X. :(
Isso deve ser portátil em diferentes plataformas e shells. Ele usa pscomo outras soluções, mas não depende sedou awkfiltra o lixo da tubulação e psele próprio, para que o shell sempre seja a última entrada. Dessa forma, não precisamos confiar em variáveis PID não portáveis ou escolher as linhas e colunas certas.
Eu testei no Debian e no macOS com Bash, Z shell ( zsh) e fish (que não funciona com a maioria dessas soluções sem alterar a expressão especificamente para fish, porque ele usa uma variável PID diferente).
Tentei isso enquanto usava zsh, e isso me deu -bash.
User137369
No meu sistema (agora), testado com bash e dash, esse retorno mutt...: -b
F. Hauri 05/02
1
Não é necessário receber o PID da saída de "ps", porque você pode ler a respectiva linha de comando para qualquer PID da estrutura de diretório / proc:
echo $(cat /proc/$$/cmdline)
No entanto, isso pode não ser melhor do que simplesmente:
echo $0
Sobre a execução de um shell realmente diferente do que o nome indica, uma idéia é solicitar a versão do shell usando o nome que você obteve anteriormente:
<some_shell> --version
sh parece falhar com o código de saída 2, enquanto outros fornecem algo útil (mas não consigo verificar tudo porque não os tenho):
Esta não é uma solução muito limpa, mas faz o que você deseja.
# MUST BE SOURCED..
getshell(){local shell="`ps -p $$ | tail -1 | awk '{print $4}'`"
shells_array=(# It is important that the shells are listed in descending order of their name length.
pdksh
bash dash mksh
zsh ksh
sh
)local suited=falsefor i in ${shells_array[*]};doif![-z `printf $shell | grep $i`]&&! $suited;then
shell=$i
suited=truefidone
echo $shell
}
getshell
Agora você pode usar $(getshell) --version.
Isso funciona, porém, apenas em conchas do tipo KornShell (ksh).
"Isso funciona, porém, apenas em conchas do tipo ksh". Você está dizendo que eu tenho que verificar o shell antes de executar isso? Hmm ...
jpaugh 17/08/16
@jpaugh, as listas devem ser suportados pelo shell terceirização este código, o que não é o caso dash, yashetc. Normalmente, se você estiver usando bash, zsh, ksh, seja qual for - você deve se preocupam com essas coisas.
theoden8
Então você está contando o bash como "ksh-like"? Entendi. Isso faz mais sentido
jpaugh 18/08/16
@ jpaugh, bem, foi isso que eu quis dizer, porque ksho conjunto de recursos é principalmente um subconjunto de bashrecursos (ainda não o verifiquei completamente).
theoden8
1
Faça o seguinte para saber se o seu shell está usando o Dash / Bash.
ls –la /bin/sh:
se o resultado for /bin/sh -> /bin/bash==> Então seu shell está usando o Bash.
se o resultado for /bin/sh ->/bin/dash==> Então seu shell está usando o Dash.
Se você deseja mudar de Bash para Dash ou vice-versa, use o código abaixo:
ln -s /bin/bash /bin/sh (mude o shell para Bash)
Nota : Se o comando acima resultar em um erro dizendo: / bin / sh já existe, remova o / bin / sh e tente novamente.
O primeiro é um absurdo, echo $SHELLfaz o que você está tentando fazer e faz bem. O segundo também não é bom, porque $SHELLa variável de ambiente contém shell padrão para um usuário atual, não um shell em execução no momento. Se eu tiver bashdefinido, por exemplo , como shell padrão, execute zshe echo $SHELL, ele será impresso bash.
David Ferenczy Rogožan 14/10
Você está correto, Dawid Ferenczy. Podemos usar o comando ps para determinar o shell atual. [# ps -p $$ | cauda -1 | awk '{print $ 4}'].
!
substitui?) É provavelmente mais portátil do que encontrar o nome do shell. Costume local pode ter você correndo algo chamado/bin/sh
que poderia realmente ser cinzas, traço, festança, etc.Respostas:
Existem três abordagens para encontrar o nome do executável do shell atual:
Observe que todas as três abordagens podem ser enganadas se o executável do shell for
/bin/sh
, mas é realmente renomeadobash
, por exemplo (o que geralmente acontece).Assim, sua segunda pergunta sobre se a
ps
saída servirá é respondida com " nem sempre ".echo $0
- imprimirá o nome do programa ... que, no caso do shell, é o shell real.ps -ef | grep $$ | grep -v grep
- isso procurará o ID do processo atual na lista de processos em execução. Como o processo atual é o shell, ele será incluído.Isso não é 100% confiável, pois você pode ter outros processos cuja
ps
lista inclui o mesmo número que o ID do processo do shell, especialmente se esse ID for um número pequeno (por exemplo, se o PID do shell for "5", você poderá encontrar processos chamados "java5" ou "perl5" na mesmagrep
saída!). Este é o segundo problema com a abordagem "ps", além de não poder confiar no nome do shell.echo $SHELL
- O caminho para o shell atual é armazenado como aSHELL
variável para qualquer shell. A ressalva é que, se você iniciar um shell explicitamente como um subprocesso (por exemplo, não é o seu shell de login), obterá o valor do shell de login. Se for possível, use a abordagemps
ou$0
.Se, no entanto, o executável não corresponder ao seu shell real (por exemplo,
/bin/sh
é realmente bash ou ksh), você precisará de heurísticas. Aqui estão algumas variáveis ambientais específicas para várias conchas:$version
está definido no tcsh$BASH
é definido no bash$shell
(minúsculo) é definido como o nome real do shell em csh ou tcsh$ZSH_NAME
está definido no zshO ksh possui
$PS3
e$PS4
define, enquanto o shell Bourne normal (sh
) apenas possui$PS1
e$PS2
define. Isso geralmente parece ser o mais difícil de distinguir - a única diferença em todo o conjunto de variáveis de ambiente entresh
eksh
temos instalado no Solaris boxen é$ERRNO
,$FCEDIT
,$LINENO
,$PPID
,$PS3
,$PS4
,$RANDOM
,$SECONDS
, e$TMOUT
.fonte
ps -p $$
como Matthew Slattery aponta. Paraksh
:echo $KSH_VERSION
ouecho ${.sh.version}
.echo ${.sh.version}
retorna "Substituição incorreta". Veja minha solução acimaps -ef | grep …
… Isso não é 100% confiável como…” O uso de uma expressão regular simples viaegrep
ougrep -e
pode facilmente trazer a confiabilidade até 100% para todos os efeitos -ps -ef | egrep "^\s*\d+\s+$$\s+"
. As^
marcas certeza de que estamos a partir do início da linha, os\d+
come-se o UID, o$$
corresponde ao PID, eo\s*
e\s+
conta para e garantir espaço em branco entre as outras partes.ps -ef | awk '$2==pid' pid=$$
ps -p $$
deve funcionar em qualquer lugar que as soluções que envolvem
ps -ef
e funcionemgrep
(em qualquer variante Unix que suporte opções POSIXps
) e não sofrerá com os falsos positivos introduzidos pelo grepping para uma sequência de dígitos que pode aparecer em outro lugar.fonte
ps
que pode não ser entendida,-p
portanto, você pode precisar usá-lo/bin/ps -p $$
.$$
exceto asfish
que você precisaria usarps -p %self
./bin/ps
.ps
poderia facilmente (atualmente é bastante normal hoje em dia) ser instalado no/usr/bin
.$(which ps) -p $$
é uma maneira melhor. Obviamente, isso não funcionará em peixes e, possivelmente, em outras conchas. Eu acho que é(which ps) -p %self
em peixe.readlink /proc/$$/exe
sh
for emulado porbash
, ps -p lhe dará/usr/bin/bash
até você executá-lo como #sh
Tentar
ou
fonte
ps -o fname --no-headers $$
.test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash
. (A próxima linha no meu script tem o equivalente para csh.)-q
vez de-p
:SHELL=$(ps -ocomm= -q $$)
Se você apenas deseja garantir que o usuário esteja chamando um script com o Bash:
fonte
#!/bin/bash
:if [ ! -n "$BASH" ] ;then exec bash $0; fi
. Com esta linha, o script é executado usando o bash, mesmo que você comece a usar o ksh ou sh. Meu caso de uso não precisa de argumentos de linha de comando, mas eles podem ser adicionados depois,$0
se necessário.Podes tentar:
Ou:
fonte
/pattern/ { action }
fará?$SHELL
A variável de ambiente contém um shell, que é configurado como padrão para um usuário atual. Ele não reflete um shell, que está sendo executado no momento. Também é melhor usar dops -p $$
que grepping $$ por causa de falsos positivos.awk
,ps | awk '$1=='$$' { n=split($4,a,"/"); print a[n] }'
$SHELL
nem sempre é necessário mostrar o shell atual. Ele reflete apenas o shell padrão a ser chamado.Para testar o que
bash
foi dito acima, digamos que é o shell padrão, tenteecho $SHELL
e, no mesmo terminal, entre em outro shell ( KornShell (ksh), por exemplo) e tente$SHELL
. Você verá o resultado como bash nos dois casos.Para obter o nome do shell atual, use
cat /proc/$$/cmdline
. E o caminho para o shell executável porreadlink /proc/$$/exe
.fonte
/proc
.ps é o método mais confiável. Não é garantido que a variável de ambiente SHELL seja configurada e, mesmo que seja, ela pode ser facilmente falsificada.
fonte
Eu tenho um truque simples para encontrar o shell atual. Basta digitar uma sequência aleatória (que não é um comando). Ele falhará e retornará um erro "não encontrado", mas no início da linha, ele dirá qual shell é:
fonte
echo 'aaaa' > script; chmod +x script; ./script
dá./script.sh: 1: aaaa: not found
O seguinte sempre fornecerá o shell real usado - ele obtém o nome do executável real e não o nome do shell (por exemplo, em
ksh93
vez deksh
etc.). Pois/bin/sh
, mostrará o shell atual usado, iedash
.Sei que muitos dizem que a
ls
saída nunca deve ser processada, mas qual é a probabilidade de você usar um shell nomeado com caracteres especiais ou colocado em um diretório nomeado com caracteres especiais? Se esse ainda for o caso, há muitos outros exemplos de como fazê-lo de maneira diferente.Conforme apontado por Toby Speight , essa seria uma maneira mais adequada e mais limpa de conseguir o mesmo:
fonte
/proc
. Nem todo mundo é um Linux.basename $(readlink /proc/$$/exe)
als
+sed
+echo
.ash -> /bin/busybox
, isso fornecerá / bin / busybox.Eu tentei muitas abordagens diferentes e a melhor para mim é:
Também funciona com Cygwin e não pode produzir falsos positivos como grepping de PID. Com alguma limpeza, ele gera apenas um nome executável (em Cygwin com path):
Você pode criar uma função para não precisar memorizá-la:
... e então apenas execute
shell
.Foi testado no Debian e Cygwin.
fonte
ps
,tail
egawk
, cmd não define$$
como PID, então definitivamente não pode funcionar sob o cmd comum.ps -p$$ -o comm=
? O POSIX diz que especificar todos os cabeçalhos vazios suprime completamente o cabeçalho. Ainda estamos falhando (como todas asps
respostas) quando somos originados por um script executado diretamente (por exemplo#!/bin/sh
).Minha variante na impressão do processo pai:
Não execute aplicativos desnecessários quando o AWK puder fazer isso por você.
fonte
awk
, quandops -p "$$" -o 'comm='
pode fazer isso por você?Existem muitas maneiras de descobrir o shell e sua versão correspondente. Aqui estão alguns que funcionaram para mim.
Direto
Abordagem Hackish
$> ******* (Digite um conjunto de caracteres aleatórios e, na saída, você obterá o nome do shell. No meu caso -bash: chapter2-a-sample-isomorphic-app: comando não encontrado )
fonte
Desde que você
/bin/sh
suporte o padrão POSIX e seu sistema possua olsof
comando instalado - uma possível alternativa possívellsof
neste casopid2path
- você também pode usar (ou adaptar) o seguinte script que imprime caminhos completos:fonte
-i
(-> ignore environment)env
na linha em que você verifica alsof
disponibilidade. ele falha com:env -i PATH="${PATH}" type lsof
->env: ‘type’: No such file or directory
Se você quiser apenas verificar se está executando (uma versão específica do) Bash, a melhor maneira de fazer isso é usar a
$BASH_VERSINFO
variável de matriz. Como uma variável de matriz (somente leitura), ela não pode ser definida no ambiente, portanto, você pode ter certeza de que está vindo (se houver) do shell atual.No entanto, como o Bash tem um comportamento diferente quando chamado como
sh
, você também precisa verificar a$BASH
variável de ambiente que termina com/bash
.Em um script que escrevi que usa nomes de funções com
-
(sem sublinhado) e depende de matrizes associativas (adicionadas no Bash 4), tenho a seguinte verificação de integridade (com mensagem de erro útil do usuário):Você pode omitir a verificação funcional um tanto paranóica de recursos no primeiro caso e apenas assumir que versões futuras do Bash seriam compatíveis.
fonte
Nenhuma das respostas funcionou com o
fish
shell (ele não possui as variáveis$$
ou$0
).Isso funciona para mim (testadas
sh
,bash
,fish
,ksh
,csh
,true
,tcsh
, ezsh
; openSUSE 13.2):Este comando gera uma string como
bash
. Aqui eu só estou usandops
,tail
esed
(sem extesions GNU; tentar adicionar--posix
para verificá-lo). Todos eles são comandos POSIX padrão. Tenho certeza quetail
pode ser removido, mas meused
fu não é forte o suficiente para fazer isso.Parece-me que esta solução não é muito portátil, pois não funciona no OS X. :(
fonte
sed: invalid option -- 'E'
no bash 3.2.51 e tcsh 6.15.00Minha solução:
Isso deve ser portátil em diferentes plataformas e shells. Ele usa
ps
como outras soluções, mas não dependesed
ouawk
filtra o lixo da tubulação eps
ele próprio, para que o shell sempre seja a última entrada. Dessa forma, não precisamos confiar em variáveis PID não portáveis ou escolher as linhas e colunas certas.Eu testei no Debian e no macOS com Bash, Z shell (
zsh
) e fish (que não funciona com a maioria dessas soluções sem alterar a expressão especificamente para fish, porque ele usa uma variável PID diferente).fonte
De Como você sabe qual é o seu shell atual? .
fonte
grep $$
não é confiável.ps -ef | awk -v pid=$$ '$2==pid { print $8 }'
é melhor, mas por que não usarps -p $$
?No Mac OS X (e FreeBSD):
fonte
zsh
, e isso me deu-bash
.mutt
...: -bNão é necessário receber o PID da saída de "ps", porque você pode ler a respectiva linha de comando para qualquer PID da estrutura de diretório / proc:
No entanto, isso pode não ser melhor do que simplesmente:
Sobre a execução de um shell realmente diferente do que o nome indica, uma idéia é solicitar a versão do shell usando o nome que você obteve anteriormente:
sh
parece falhar com o código de saída 2, enquanto outros fornecem algo útil (mas não consigo verificar tudo porque não os tenho):fonte
Esta não é uma solução muito limpa, mas faz o que você deseja.
Agora você pode usar
$(getshell) --version
.Isso funciona, porém, apenas em conchas do tipo KornShell (ksh).
fonte
dash
,yash
etc. Normalmente, se você estiver usandobash
,zsh
,ksh
, seja qual for - você deve se preocupam com essas coisas.ksh
o conjunto de recursos é principalmente um subconjunto debash
recursos (ainda não o verifiquei completamente).Faça o seguinte para saber se o seu shell está usando o Dash / Bash.
ls –la /bin/sh
:se o resultado for
/bin/sh -> /bin/bash
==> Então seu shell está usando o Bash.se o resultado for
/bin/sh ->/bin/dash
==> Então seu shell está usando o Dash.Se você deseja mudar de Bash para Dash ou vice-versa, use o código abaixo:
ln -s /bin/bash /bin/sh
(mude o shell para Bash)Nota : Se o comando acima resultar em um erro dizendo: / bin / sh já existe, remova o / bin / sh e tente novamente.
fonte
E eu vim com isso
fonte
Por favor, use o comando abaixo:
fonte
echo $SHELL
faz o que você está tentando fazer e faz bem. O segundo também não é bom, porque$SHELL
a variável de ambiente contém shell padrão para um usuário atual, não um shell em execução no momento. Se eu tiverbash
definido, por exemplo , como shell padrão, executezsh
eecho $SHELL
, ele será impressobash
.echo $SHELL
pode ser lixo:~ $ echo $SHELL /bin/zsh ~ $ bash bash-4.3$ echo $SHELL /bin/zsh bash-4.3$
Este funciona bem no Red Hat Linux (RHEL), macOS, BSD e alguns AIXes :
alternativamente, o seguinte também deve funcionar se pstree estiver disponível,
fonte