Executando um script de shell quando "/ bin / sh" aponta para "/ bin / bash"

11

Eu li o seguinte nesta pergunta :

O bash suporta um switch --posix, que o torna mais compatível com POSIX. Ele também tenta imitar o POSIX se invocado como sh .

A citação acima assume que /bin/shé um link que aponta para /bin/bash.

Mas não entendo bem o que se entende por "invocado como sh" .


Diga que eu tenho o seguinte script chamado "script.sh":

#!/bin/bash
echo "Hello World"

Diga-me, em cada um dos seguintes casos, se o script será executado no bashmodo normal ou no modo POSIX (suponha que eu executei os seguintes comandos em um terminal em execução bash):

  1. sh script.sh
  2. bash script.sh
  3. ./script.sh

Agora diga que eu tenho o seguinte script chamado "script.sh" (que é como o script acima, mas sem o shebang):

echo "Hello World"

Diga-me, em cada um dos seguintes casos, se o script será executado no bashmodo normal ou no modo POSIX (suponha que eu executei os seguintes comandos em um terminal em execução bash):

  1. sh script2.sh
  2. bash script2.sh
  3. ./script2.sh
user269904
fonte

Respostas:

19

Apenas os casos 1 e 4 serão executados no modo POSIX (assumindo que o shbash e não alguma outra implementação do sh). Qualquer caso que chame explicitamente bashsem --posix, não será, seja do shebang ou não. Qualquer caso que ligue explicitamente shserá. O shebang é usado apenas quando nenhum shell já foi explicitamente iniciado para o script.

Caso 6, se o seu terminal estiver em execução bash, não será executado no modo POSIX e o Bash o chamará usando-se. Se o seu terminal estivesse executando o zsh, o caso 6 também seria executado no modo POSIX. O POSIX é ambíguo sobre exatamente o que deveria acontecer nesse caso , e Bash e zsh fizeram escolhas diferentes lá. O Bash chama o script usando-se, enquanto o zsh usa sh(o que quer que seja). Outras conchas também variam nesse ponto.


Uma maneira simples de dizer em que modo você está é criar o corpo do script:

kill -SIGHUP

que falhará com um erro no modo POSIX , mas fornecerá instruções de uso para killfora dele. Essa é uma distinção fácil e funciona através de uma longa variedade de versões do Bash, que remontam até onde você provavelmente encontrará.

Michael Homer
fonte
3
Existem outras coisas que forçarão basha execução no modo POSIX, como a POSIXLY_CORRECTvariável de ambiente ou SHELLOPTS=posix.
Stéphane Chazelas
1
[ -o posix ]é uma maneira mais óbvia de verificar se você está executando no modo posix no bash (não em outros shells (exceto yash), para que não queira fazer isso em um shscript). POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'saídas yes`
Stéphane Chazelas 11/01
2
No caso 6, o bash chama o script consigo no modo POSIX quando ele próprio está no modo POSIX, conforme o POSIX exige. O POSIX não especifica o mecanismo she-bang e 6 é a única maneira do POSIX de ter scripts executáveis ​​e é claramente especificado (em ambientes POSIX, o script deve ser interpretado por um utilitário sh compatível).
Stéphane Chazelas
8

O "invocado como" refere-se a qualquer coisa que o processo que inicia o Bash coloca em seu argumento de linha de comando "zeroth" argv[0],.

Quando um programa é iniciado com os exec*()syscalls , eles realmente não conhecem o nome do arquivo binário que contém o programa, mas o processo de chamada é livre para colocar o que quiser lá. Normalmente, é claro, o nome é retirado do sistema de arquivos, portanto, se você executar /bin/sh, é isso que é colocado lá. E se /bin/shfor o Bash, ele não precisa ser um link simbólico, pode ser um link físico ou apenas outra cópia do programa shell.

Como um exemplo de configuração do "nome do programa", o execcomando do Bash pode definir o argumento zeroth com a -aopção (Poderíamos fazer o mesmo com Perl, ou diretamente com C, etc.)

Aqui mynameestá um programa C simples que apenas imprime seu argumento zero, o nome que ele próprio vê:

$ ./myname 
I am ./myname
$ (exec -a something ./myname )
I am something
$ mv ./myname somename
$ ln -s somename othername
$ ./somename 
I am ./somename
$ ./othername
I am ./othername

Fonte:

#include <stdio.h>
int main(int argc, char *argv[]) {
    printf("I am %s\n", argv[0]);
    return 0;
}

Mas, para responder às perguntas numeradas ...

(1 e 4) a execução sh somescriptexecutará o que shestiver no seu PATH, provavelmente, /bin/shmas possivelmente algo como/usr/xpg4/bin/sh .

  • Se for o Bash, ele será executado no modo POSIX, pois ele vê o nome sh.
  • Se for o shell Z ou o shell Korn, ele também verá o nome sh, mas será executado no modo "Compatível com SH", que visa ser compatível com o shell Bourne e é sutilmente diferente do modo compatível com POSIX completo em ambos os shells. .
  • Poderia ser a concha Almquist, uma concha Bourne real, ou qualquer outra coisa, é claro.

(2 e 5) A corrida bash somescriptserá executada no modo Bash regular (novamente, é claro, depende do que está bashno seu PATH.)

(3) Aqui, o nome do script é dado diretamente à chamada do sistema no lugar do arquivo do programa. O kernel lê a linha hashbang e a usa para executar o script.

(6) Esse é o complexo. É semelhante a (3), mas a chamada do sistema para iniciar o programa falha ( ENOEXEC (Exec format error)), pois não há linha hashbang. O que acontece a seguir depende de se o shell que você está executando é em si no modo POSIX. O POSIX requer que um shell compatível com POSIX se comporte de uma maneira específica em resposta a ENOEXEC. No entanto, há alguma margem de manobra em "um comando equivalente a invocar um shell", o que significa que diferentes tipos de conchas fazem coisas diferentes.

  • O shell Bourne Again é executado novamente no mesmo modo com o nome do script que seu primeiro argumento de linha de comando. Em seu modo compatível com POSIX, é claro que ele está se executando no modo compatível com POSIX, obedecendo, assim, ao requisito POSIX de invocar um shell compatível com POSIX.
  • O shell Z, o shell Almquist e o Korn são executados /bin/shcom o nome do script inserido antes dos outros argumentos como o primeiro argumento da linha de comando. O shell Z, o shell Almquist e o Korn estão (tentando) invocar um shell compatível com POSIX com a suposição de que o /bin/shprograma é um.
ilkkachu
fonte
Poderia, por favor compartilhar o código fonte desse programa de C ..
GypsyCosmonaut
int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
precisa saber é o seguinte
É isso mesmo.
ilkkachu
4

O shell executado é tanto o chamado na linha de comando ou a do shebang (se a linha de comando não especificá-lo).

Portanto, as versões 1 e 4 serão executadas com sh, 2 e 5 com bash e 6 podem não ser executadas se você estiver usando sh (e alguns outros) interativamente. Bash inicia o script. Ksh também. Zsh começa como sh.

Somente aqueles iniciados como shusarão a opção posix se o bash estiver vinculado /bin/sh.

Adicione esta linha ao seu script para detectar se alguma versão do bash ksh ou zsh está executando:

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"
NotAnUnixNazi
fonte