Suponha que o shell padrão da minha conta seja zsh, mas eu abri o terminal e iniciei o bash e executei um script chamado prac002.sh
, qual interpretador de shell seria usado para executar o script, zsh ou bash? Considere o seguinte exemplo:
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % sudo cat /etc/passwd | grep papagolf
[sudo] password for papagolf:
papagolf:x:1000:1001:Rex,,,:/home/papagolf:/usr/bin/zsh
# papagolf's default shell is zsh
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % bash
# I fired up bash. (See that '%' prompt in zsh changes to '$' prompt, indicating bash.)
papagolf@Sierra:~/My Files/My Programs/Learning/Shell$ ./prac002.sh
Enter username : Rex
Rex
# Which interpreter did it just use?
** EDIT: ** Aqui está o conteúdo do script
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % cat ./prac002.sh
read -p "Enter username : " uname
echo $uname
. prac002.sh
, assumindo que seu script esteja no diretório atual.. ./prac002.sh
e ele será executado com o shell atual, ou seja, ponto (.
), espaço () seguido pelo caminho do seu script. Isso se chama fonte de pontos do seu script. ;-)Respostas:
Como o script não começa com uma
#!
linha shebang indicando qual intérprete usar, o POSIX diz que :Essa frase é um pouco ambígua e conchas diferentes têm interpretações diferentes.
Nesse caso, o Bash executará o script usando-se . Por outro lado, se você o executasse a partir do zsh, o zsh usaria
sh
(o que quer que esteja no seu sistema).Você pode verificar esse comportamento para este caso adicionando estas linhas ao script:
Você notará que, no Bash, a primeira linha gera sua versão, enquanto a segunda nunca diz nada, independentemente do shell que você usa.
/bin/sh
é, digamosdash
,, nenhuma linha produzirá nada quando o script for executado a partir do zsh ou dash./bin/sh
é um link para o Bash, verá a primeira linha de saída em todos os casos./bin/sh
houver uma versão diferente do Bash do que você estava usando diretamente, você verá uma saída diferente ao executar o script diretamente do bash e do zsh.O
ps -p $$
comando da resposta do rools também mostrará informações úteis sobre o comando que o shell usou para executar o script.fonte
execl()
chamada acontece quando um script de shell não contém um shebang e é executado comoscriptname
? Isso não acontece quando um script de shell é executado comobash scriptname
? Isso não acontece quando um script de shell contém um shebang e é executado comoscriptname
?Como o arquivo não é de nenhum dos tipos de executáveis reconhecidos pelo sistema e, assumindo que você tem permissão para executá-lo, a
execve()
chamada do sistema normalmente falhará com um erroENOEXEC
( não executável ).O que acontece então depende da aplicação e / ou função da biblioteca usada para executar o comando.
Pode ser, por exemplo, um shell, a função
execlp()
/execvp()
libc.A maioria dos outros aplicativos usará um deles quando executar um comando. Eles invocam um shell, por exemplo, por meio da
system("command line")
função libc, que normalmente invocash
para analisar essa linha de comando (cujo caminho pode ser determinado em tempo de compilação (como/bin/sh
vs/usr/xpg4/bin/sh
no Solaris)), ou invoca o shell armazenado$SHELL
por eles mesmos, comovi
com seu!
comando ou comxterm -e 'command line'
muitos outros comandos (su user -c
invocará o shell de login do usuário em vez de$SHELL
).Geralmente, um arquivo de texto sem shebang que não inicia
#
é considerado como umsh
script. Qualsh
é o que irá variar embora.execlp()
/execvp()
, aoexecve()
retornarENOEXEC
, normalmente o invocarásh
. Para sistemas que possuem mais de um,sh
porque podem estar em conformidade com mais de um padrão, o quesh
normalmente será determinado no momento da compilação (do aplicativo usandoexecvp()
/execlp()
vinculando um blob diferente de código que se refere a um caminho diferente parash
). Por exemplo, no Solaris, isso será/usr/xpg4/bin/sh
(um padrão, POSIXsh
) ou/bin/sh
(o shell Bourne (um shell antiquado) no Solaris 10 e mais antigo, ksh93 no Solaris 11).Quando se trata de conchas, há muita variação.
bash
, AT&Tksh
, o shell Bourne normalmente interpreta o próprio script (em um processo filho, a menos queexec
seja usado) depois de simular aexecve()
, que está desmarcada todas as variáveis não exportadas, fechou todos os fds de execução imediata, removeu todas as traps personalizadas, aliases, funções ... (bash
interpretará o script nosh
modo).yash
se executará (comsh
oargv[0]
modo nosh
modo) para interpretá-lo.zsh
,pdksh
,ash
Conchas baseados irá tipicamente invocarsh
(o caminho de que determinado no momento da compilação).Para
csh
etcsh
(e osh
de alguns BSDs iniciais), se o primeiro caractere do arquivo for#
, eles se executarão para interpretá-lo e desh
outra forma. Isso remonta a um período pré-shebang, ondecsh
ele reconheceu#
como comentários, mas não o shell Bourne, então#
havia uma dica de que era um script csh.fish
(pelo menos versão 2.4.0), apenas retorna um erro seexecve()
falhar (ele não tenta tratá-lo como um script).Alguns shells (como a
bash
AT&Tksh
) primeiro tentarão determinar heuristicamente se o arquivo provavelmente deve ser um script ou não. Portanto, você pode achar que alguns shells se recusam a executar um script se ele tiver um caractere NUL nos primeiros bytes.Observe também que, se houver
execve()
falha no ENOEXEC, mas o arquivo tiver uma linha shebang, alguns shells tentarão interpretar essa linha shebang.Então, alguns exemplos:
$SHELL
estiver/bin/bash
,xterm -e 'myscript with args'
terámyscript
interpretado porbash
nosh
modo. Enquanto estiver comxterm -e myscript with args
,xterm
usaráexecvp()
para que o script seja interpretado porsh
.su -c myscript
no Solaris 10, onderoot
o shell de logon é/bin/sh
e/bin/sh
é o shell Bourne terá sidomyscript
interpretado pelo shell Bourne./usr/xpg4/bin/awk 'BEGIN{system("myscript")'
no Solaris 10, ele será interpretado por/usr/xpg4/bin/sh
(o mesmo para/usr/xpg4/bin/env myscript
).find . -prune -exec myscript {} \;
no Solaris 10 (usandoexecvp()
), ele será interpretado por/bin/sh
even with/usr/xpg4/bin/find
, mesmo em um ambiente POSIX (um erro de conformidade).csh -c myscript
terá interpretado porcsh
se começa com#
, com osh
contrário.Em suma, você não pode ter certeza de qual shell será usado para interpretar esse script se você não souber como e pelo que será chamado.
De qualquer forma,
read -p
ébash
apenas uma sintaxe, portanto, você deve garantir que o script seja interpretado porbash
(e evitar essa.sh
extensão enganosa ). Você conhece o caminho dobash
executável e usa:Ou você pode tentar confiar na
$PATH
pesquisa dobash
executável (supondo quebash
esteja instalado) usando:(
env
é quase onipresente encontrado em/usr/bin
). Como alternativa, você pode torná-lo compatível com POSIX + Bourne e, nesse caso, você pode usá-lo/bin/sh
. Todos os sistemas terão a/bin/sh
. Na maioria deles, é (na maior parte) compatível com POSIX, mas você ainda pode encontrar de vez em quando um shell Bourne lá.fonte
Quando você não possui nenhuma linha
#!
(chamada shebang ), sh é usado. Para verificar isso, você pode executar o seguinte script.No meu computador eu recebo
mesmo que meu shell padrão seja zsh . Ele usa o bash, pois na minha máquina, o comando sh é implementado pelo bash .
fonte