Por que este softlink 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 é fedora 24 (versão padrão do GNOME).

No exemplo, podemos saber: em /bin , bash é um executável binário; sh é um link para bash .

Então, que eu saiba, type bash and press enter deve efetuar o mesmo resultado exatamente como type sh and press enter .

Quando eu type bash and press enter , recebo [root@localhost bin]# como esperado.

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

Qual é a causa?

    
por xmllmx 20.07.2016 / 05:30

1 resposta

25

Esse é um recurso documentado.

Se você executar o bash através de um link simbólico chamado sh , o bash iniciará no modo de compatibilidade sh .

De man bash :

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well. When invoked as an interactive login shell, or a non-interactive shell with the --login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The --noprofile option may be used to inhibit this behavior. When invoked as an interactive shell with the name sh, bash looks for the variable ENV, expands its value if it is defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked as sh does not attempt to read and execute commands from any other startup files, the --rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When invoked as sh, bash enters posix mode after the startup files are read.

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

Se for um programa c, ele pode inspecionar argv[0] . Se for um script shell ou 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, utc e et executam o mesmo executável, mas fornecem resultados diferentes. Quando executado como utc , ele exibe o horário universal. Quando executado como et , sai a hora da Costa Leste dos EUA. Por exemplo:

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016
    
por 20.07.2016 / 05:41