As funções são executadas como subprocessos no Bash?

28

No Advanced Bash-Scripting Guide , no exemplo 27-4 , 7ª linha da parte inferior, li o seguinte:

Uma função é executada como um subprocesso.

Fiz um teste no Bash e parece que a declaração acima está errada.

As pesquisas neste site, Bash Man e meu mecanismo de pesquisa não trazem nenhuma luz.

Você tem a resposta e gostaria de explicar?

Tomasz
fonte
12
Como observado, esse guia é enganoso ao extremo. Eu recomendo o Guia Wooledge Bash .
Curinga

Respostas:

36

O Advanced Bash-Scripting Guide nem sempre é confiável e seus scripts de exemplo contêm práticas desatualizadas, como o uso de backticks efetivamente preteridos para substituição de comandos, ou seja, em `command`vez de $(command).

Nesse caso em particular, é flagrantemente incorreto.

A seção Funções do Shell no manual Bash (canônico) afirma definitivamente que

As funções do shell são executadas no contexto atual do shell; nenhum novo processo é criado para interpretá-los.

Anthony G - justiça para Monica
fonte
10
"O Advanced Bash-Scripting Guide geralmente não é confiável" . Verdade.
precisa saber é o seguinte
1
Você pode dar referências para apoiar sua primeira frase?
Will Vousden
5
@WillVousden, como seria uma referência aqui? Um monte de exemplos de deficiências técnicas do guia? Um documento em que especialistas da comunidade do bash observaram anteriormente que não é confiável? Ajudaria se um membro do stackoverflow com um distintivo dourado no bash concordasse em um comentário? : p
kojiro 24/08
3
@ WillVousden Eu não acho que o que você quer exista de uma forma confiável. Mendel Cooper atualizou e corrigiu problemas com o guia no passado, mas não há rastreador de erros público ou lista de erratas. (Talvez essa seja a declaração mais condenatória que posso fazer.) Portanto, quando encontramos uma falha (percebida ou real), tudo o que podemos fazer é enviar um e-mail ao autor e esperar o melhor.
Kojiro # 24/16
3
@WillVousden, ... se você quiser um histórico de quanto tempo o consenso no canal #breen freenode tem sido de que o ABS deve ser evitado, consulte wooledge.org/~greybot/meta/abs - o segundo campo em cada linha é o carimbo de data e hora e o primeiro é o nome de usuário; Espero que seja suficiente a afirmação de que os nomes de usuário em questão são indivíduos muito respeitados.
Charles Duffy
32

As funções de chaves curvadas serão executadas dentro do processo do shell de chamada, a menos que precisem de seu próprio subshell, que é:

  • quando você os executa em segundo plano com &
  • quando você os executa como um link em um pipeline

Redirecionamentos ou env extra. variáveis ​​não forçam um novo subshell:

hw(){
    echo hello world from $BASHPID
    echo var=$var
} 
var=42 hw >&2
echo $BASHPID  #unexports var=42 and restores stdout here

Se você definir a função entre parênteses, em vez de curvas:

hw()(
  echo hello world from $BASHPID
)
hw 
echo $BASHPID

sempre será executado em um novo processo.

A substituição de comandos $()também sempre cria processos no bash (mas não no ksh se você executar os componentes internos dentro dele).

PSkocik
fonte
Eu não sabia que f() (...)é permitido. Existem outras definições além de {...}e (...)? No Bash, ainda não gosto de outras pessoas.
Tomasz
1
@tomas Você pode usar a function hw { echo hello world; } sintaxe (sem necessidade de ()se digitar functione você pode especificar redirecionamentos logo após a final }ou )como no hw(){ echo error; } >&2que é sobre ele..
PSkocik
2
Esta é a resposta em que pensei imediatamente e é absolutamente correta. Deve ser votado como a resposta correta. f()(...)sempre execute um próprio shell, enquanto f(){...}não.
Rexkogitans
11
As funções bash do NB aceitam qualquer comando composto, assim foo() [[ x = x ]]como uma definição de função válida também. No entanto, se você olhar para a função, type fooverá que ainda é um açúcar sintático foo() { [[ x = x ]]; }. O mesmo vale para as funções do subshell: bar() ( : )torna - se bar() { ( : ); }.
Kojiro #
1
@kojiro nice +1. não sabia que
PSkocik
9

O comando em questão desse exemplo se parece com:

echo ${arrayZ[@]/%e/$(replacement)}

O exemplo posterior afirma:

#    $( ... ) is command substitution.
#    A function runs as a sub-process.

Sendo caridoso com o ABS Guide, o que eles aparentemente pretendiam escrever é que a função é executada dentro de uma substituição de comando e o comando dentro de uma substituição de comando é executado em uma subshell .

John1024
fonte
Isso é muito enganador. Obrigado pela sua interpretação.
Tomasz
5
@tomas "muito enganadores". Sim muito. Em contraste com o Guia do ABS, o Greg's Wiki é uma excelente fonte de informações avançadas sobre o bash.
precisa saber é o seguinte
1
Felicidades. Qual sua opinião sobre este: wiki.bash-hackers.org/start ?
Tomasz
@tomas Não tenho conhecimento em primeira mão desse.
precisa saber é o seguinte
2
@tomas, ... minha opinião quanto ao wiki do bash-hackers é que é uma excelente fonte. Eu não passei por isso de maneira tão abrangente quanto eu tenho no wiki do Wooledge, mas tende a ser exato e preciso.
Charles Duffy