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

Em Guia de script Bash avançado , em exemplo 27-4 , sétima linha a partir do fim, li isto:

Uma função é executada como um subprocesso.

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

Pesquisas em este site, Bash Man e meu mecanismo de pesquisa não trazem nenhuma luz.

Você tem a resposta e gostaria de explicar?

Comentários

  • Como observado, esse guia é enganador ao extremo. Em vez disso, recomendo o Guia Wooledge Bash .
  • Um fato importante é que ” Bash ” evita criar subshells. Eles são caros, possuem ambiente próprio e afetam o desempenho do script e também a forma como o código flui (muitas vezes, de forma inconveniente, para lidar com suas particularidades). O estado real do Bash é produto de uma evolução, uma evolução do código. Quer dizer, a primeira versão do Bash usa mais subshells *** do que a real. Esse tipo de inconsistência parece razoável. *** se você quiser uma prova, não posso ‘ dar a você. Eu ‘ deduzi-o de páginas da web, comentários … Eu ‘ li essa declaração em algum lugar atrás.

Resposta

O Guia de script Bash avançado nem sempre é confiável e seus scripts de exemplo contêm práticas desatualizadas, como o uso do efetivamente descontinuado crases para substituição de comando, ou seja, `command` em vez de $(command).

Neste caso específico, é flagrantemente incorreto.

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

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

Comentários

  • ” Guia de script Bash avançado geralmente não é confiável ” Muito verdadeiro.
  • Você pode fornecer referências para apoiar o seu primeira frase?
  • @WillVousden como seria uma referência aqui? Um monte de exemplos das deficiências técnicas do guia ‘ s? Um documento onde os especialistas da comunidade bash notaram anteriormente que ele não é confiável? Ajudaria se um membro stackoverflow com um distintivo dourado em bash concordasse em um comentário? : p
  • @WillVousden Eu não ‘ não acho que o que você quer existe em uma forma confiável. Mendel Cooper atualizou e corrigiu problemas com o guia no passado, mas não há rastreador de bug público ou lista de erratas. (Talvez essa seja a declaração mais contundente que posso fazer.) Então, quando encontramos uma falha (percebida ou real), tudo o que podemos fazer é enviar um e-mail para o autor e esperar o melhor.
  • @WillVousden, .. .se você quiser um histórico de há quanto tempo o consenso no canal freenode #bash é de que o ABS deve ser evitado, consulte lãedge.org/ ~ greybot / meta / abs – o segundo campo em cada linha é o carimbo de data / hora e o primeiro é o nome de usuário; Eu ‘ espero que seja suficiente a afirmação de que os nomes de usuário em questão são pessoas muito respeitadas.

Resposta

As funções do Curly Brace serão executadas no 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. as variáveis não irão forçar 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 com parênteses em vez de curvas:

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

ele sempre será executado em um novo processo.

A substituição do comando $() também sempre cria processos em bash (mas não em ksh se você executa builtins dentro dele).

Comentários

  • Eu não ‘ não sabia f() (...) é permitido. Existem outras definições além de {...} e (...)? No Bash, eu ‘ m não em outros ainda.
  • @tomas Você pode usar a sintaxe function hw { echo hello world; } (sem necessidade de () se você digitar function e pode especificar redirecionamentos logo após o final } ou ) como em hw(){ echo error; } >&2. Isso ‘ é sobre isso.
  • Isso é a resposta na qual pensei imediatamente, e é absolutamente correta.Deve ser votada como a resposta correta. f()(...) sempre executa um shell próprio, enquanto f(){...} não.
  • NB funções bash aceitam qualquer comando composto, portanto foo() [[ x = x ]] também é uma definição de função válida. No entanto, se você olhar para a função com type foo, ‘ verá que ainda é um açúcar sintático para foo() { [[ x = x ]]; }. O mesmo é verdadeiro para funções de subshell: bar() ( : ) torna-se bar() { ( : ); }.
  • @kojiro nice +1. não ‘ não sabia disso

Resposta

O comando em a pergunta 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 queriam 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 um subshell .

Comentários

  • Isso ‘ é muito enganador. Obrigado pela sua interpretação.
  • @tomas ” muito enganador. ” Sim, muito. Em contraste com o Guia ABS, Greg ‘ s Wiki é uma excelente fonte de informações avançadas de bash.
  • Saúde. Qual ‘ s sua opinião sobre este: wiki.bash-hackers.org/start ?
  • @tomas Não tenho nenhum conhecimento de primeira mão sobre isso.
  • @tomas, … minha própria opinião sobre o wiki do bash-hackers é que ‘ é uma excelente fonte. Eu ‘ não li isso de forma tão abrangente quanto fiz a wiki do Wooledge, mas tende a ser preciso e escrito com precisão.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *