Por que o shebang não causa a bifurcação de um programa como deveria?

2

Eu sempre declaro a linha shebang #!/bin/bashno meu script de shell. Recentemente, quando chamei um script que contém uma exitchamada, ele acabou com o meu terminal. Geralmente, mata o processo bifurcado e retorna ao prompt do meu terminal. Por que poderia ter acontecido que parou o garfo?

EDITAR

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
  • Normalmente, invoco o script usando . script_pathou através de um link simbólico para o script.
Martin
fonte
11
Como você o invocou? Qual versão do bash é?
Keith

Respostas:

5

O shebang nunca causa um processo de bifurcação. Ele não faz nada, a menos que o script seja executável e é invocado de tal maneira que faz com que o sistema avalie o shebang para ver com qual programa / shell executar o script.

Se, por exemplo, você já estivesse executando o bash e executasse o script com o sourcecomando, o script seria executado dentro do shell que você estava executando no momento e exitafetaria esse processo do shell, em vez de ser um novo shell processo que terminou.

Se você possui um arquivo de script que deseja executar, torne-o executável com o seguinte comando:

chmod +x script

Então, se você deseja executar o script, e se assumirmos que o arquivo de script está no diretório atual, use o seguinte comando:

./script

Observe que isso é muito diferente de . script, o que é apenas uma notação abreviada para source script.

O ./scripté um nome de caminho relativo ao arquivo de script, o que significa pesquisar no diretório atual para encontrar o arquivo de script 'script' e depois executá-lo - o que funciona apenas se o arquivo de script for executável.

Se você tiver um arquivo de script que NÃO seja executável, poderá invocá-lo com:

bash script

Mas, neste caso, você está especificando qual shell executar e a linha shebang é ignorada.

Zeke Hansell
fonte
Obrigado por sua resposta. Eu corro isso por ". Script". O estranho acontece de forma intermitente. Como eu disse, isso não aconteceu antes.
Martin
11
O . é uma abreviação para o comando source. Se você deseja bifurcar, precisa tornar o script executável e, em seguida, colocá-lo em seu caminho em algum lugar, para executá-lo digitando o nome ou, se não estiver no caminho, digitando um nome de caminho para o script .
Zeke Hansell
6

Como o fornecimento de um script usando .faz com que ele seja executado no shell atual, um exitfaz com que o shell atual seja encerrado. Você pode usar returnpara retornar de um script de origem e de uma função. Você não pode retornar de um script que foi executado diretamente.

Para trabalhar com essas restrições, você pode colocar um teste condicional em seu script para fazer a coisa certa, dependendo de sua origem ou execução direta.

Como a primeira linha após o shebang:

called=$_

No ponto em que você deseja sair ou retornar:

[[ $called != $0 ]] && exit || return
Dennis Williamson
fonte
Truque inteligente. Muito útil para scripts que devem ser originados para funcionar corretamente, como virtualenv activatescripts python .
fogão
@ hobs: eu incluo a seguinte linha como a primeira linha, em vez de um shebang, em qualquer script que deva ser originado:[[ $_ != $0 ]] || { echo "This file must be sourced to have any effect."; exit 1; }
Dennis Williamson
Eu acredito que isso é ao contrário - deveria ser . (PS: Você sempre deve citar todas as referências a variáveis ​​de shell, a menos que tenha um bom motivo para isso e não se esqueça do que está fazendo.) Outra abordagem que é (sem dúvida) mais intuitiva (exigindo menos arranhões) é . [[ "$called" = "$0" ]] && exit || returnreturn 2> /dev/null || exit
G-Man
@ G-Man, eu acredito que você está errado. No que diz respeito à citação, é desnecessário por dentro, [[ ]]pois a divisão de palavras etc. não ocorre lá.
Dennis Williamson
4

O shebang não causa a bifurcação de um programa; se o processo bifurca-se ou não depende de como o script é executado. O fornecimento do script fará com que ele seja executado no intérprete atual e o uso execsubstituirá o processo atual por completo.

Ignacio Vazquez-Abrams
fonte