Por que esse link não funciona como esperado?


11
bash4.3 # pwd
/bin
bash4.3 # ll sh
lrwxrwxrwx. 1   root    root    4   May 17 22:22 sh -> bash
bash4.3 # ll bash
-rwxr-xr-x. 1   root    root    1072056 May 17 22:22 bash
bash4.3 # bash
bash4.3 # sh
sh-4.3#

Meu sistema operacional é o fedora 24 (versão GNOME padrão).

A partir do exemplo, podemos saber: under /bin, bashé um executável binário; shé um link para bash.

Portanto, que eu saiba, type bash and press enterdeve efetuar o mesmo resultado exatamente como type sh and press enter.

Quando eu type bash and press enterfico [root@localhost bin]#como o esperado.

No entanto, se eu type sh and press enter, surpreendentemente entendo sh-4.3#.

Qual a causa?


O texto que pode ser facilmente copiado e colado em um editor de SE como uma imagem é bastante irritante, portanto, não faça isso. Em vez disso, selecione o texto no seu terminal e pressione CTRL-SHIFT-C.
cat

Respostas:


25

Esse é um recurso documentado.

Se você executar o bash por meio de um link simbólico chamado sh, o bash será iniciado no shmodo de compatibilidade.

De man bash:

Se o bash for chamado com o nome sh, ele tentará imitar o comportamento de inicialização das versões históricas do sh o mais próximo possível, enquanto estiver em conformidade com o padrão POSIX. Quando chamado como um shell de login interativo ou não-interativo com a opção --login, ele primeiro tenta ler e executar comandos de / etc / profile e ~ / .profile, nessa ordem. A opção --noprofile pode ser usada para inibir esse comportamento. Quando chamado como um shell interativo com o nome sh, o bash procura a variável ENV, expande seu valor se for definido e usa o valor expandido como o nome de um arquivo para ler e executar. Como um shell chamado sh não tenta ler e executar comandos de outros arquivos de inicialização, a opção --rcfile não tem efeito. Um shell não interativo chamado com o nome sh não tenta ler outros arquivos de inicialização. Quando chamado como sh, o bash entra no modo posix após a leitura dos arquivos de inicialização.

Como um programa sabe qual nome foi usado para iniciá-lo?

Se for um programa de CA, ele pode inspecionar argv[0]. Se é um shell ou script perl, ele pode inspecionar $0.

Como exemplo, vamos considerar este simples script de shell:

$ cat utc
#!/bin/sh
case "${0##*/}" in
        utc) date -u ;;
        et) TZ=US/Eastern date ;;
esac

$0é o nome pelo qual o script foi chamado. ${0##*/}é o nome que o script foi chamado com qualquer nome de diretório removido.

Vamos criar este link simbólico:

ln -s utc et

Portanto, utce etambos executam o mesmo executável, mas fornecem resultados diferentes. Quando executado como utc, gera tempo universal. Quando executado como et, é emitido no horário do leste dos EUA. Por exemplo:

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016

4
Talvez queira adicionar como isso é possível, pois o OP espera que as chamadas sejam idênticas. ( argv[0], obvs)
Lightness Races in Orbit

@LightnessRacesinOrbit Good idea. Eu adicionei um exemplo.
John1024

Perfeito agora. :)
Lightness Races in Orbit
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.