Les fonctions s'exécutent-elles en tant que sous-processus dans Bash?

28

Dans Advanced Bash-Scripting Guide , dans l' exemple 27-4 , 7ème ligne du bas, j'ai lu ceci:

Une fonction s'exécute comme un sous-processus.

J'ai fait un test dans Bash, et il semble que la déclaration ci-dessus soit fausse.

Les recherches sur ce site, Bash Man, et mon moteur de recherche n'apportent aucune lumière.

Avez-vous la réponse et souhaitez-vous expliquer?

Tomasz
la source
12
Comme indiqué, ce guide est trompeur à l'extrême. Je recommande plutôt le guide Wooledge Bash .
Wildcard

Réponses:

36

Le Guide de script Bash avancé n'est pas toujours fiable et ses exemples de scripts contiennent des pratiques obsolètes telles que l'utilisation des raccourcis efficacement déconseillés pour la substitution de commandes, c'est-à-dire `command`plutôt que $(command).

Dans ce cas particulier, c'est manifestement incorrect.

La section sur les fonctions shell du manuel (canonique) de Bash déclare définitivement que

Les fonctions shell sont exécutées dans le contexte shell actuel; aucun nouveau processus n'est créé pour les interpréter.

Anthony G - justice pour Monica
la source
10
"Le Guide avancé de Bash-Scripting n'est généralement pas fiable" Très vrai.
John1024
1
Pouvez-vous donner des références à l'appui de votre première phrase?
Will Vousden
5
@WillVousden à quoi ressemblerait une référence ici? Un tas d'exemples des lacunes techniques du guide? Un document où des experts de la communauté bash ont déjà noté qu'il n'était pas fiable? Serait-il utile qu'un membre stackoverflow avec un badge en or dans bash accepte simplement dans un commentaire? : p
kojiro
3
@WillVousden Je ne pense pas que ce que vous voulez existe sous une forme fiable. Mendel Cooper a mis à jour et corrigé des problèmes avec le guide dans le passé, mais il n'y a pas de suivi de bogues public ni de liste d'errata. (C'est peut-être la déclaration la plus accablante que je puisse faire.) Donc, quand nous trouvons une faille (perçue ou réelle), tout ce que nous pouvons faire est d'envoyer un courriel à l'auteur et d'espérer le meilleur.
kojiro
3
@WillVousden, ... si vous voulez un historique de combien de temps le consensus dans le canal #bash freenode a été que l'ABS devrait être évité, voir wooledge.org/~greybot/meta/abs - le deuxième champ de chaque ligne est l'horodatage et le premier est le nom d'utilisateur; J'espère que l'affirmation selon laquelle les noms d'utilisateur en question sont des personnes très respectées suffit.
Charles Duffy
32

Les fonctions d'accolade seront exécutées dans le processus de shell appelant, à moins qu'elles n'aient besoin de leur propre sous-shell qui est:

  • lorsque vous les exécutez en arrière-plan avec &
  • lorsque vous les exécutez en tant que lien dans un pipeline

Redirection ou env supplémentaire. les variables ne forceront pas un nouveau sous-shell:

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

Si vous définissez la fonction entre parenthèses au lieu de curlies:

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

il s'exécutera toujours dans un nouveau processus.

La substitution de commandes $()crée également toujours des processus dans bash (mais pas dans ksh si vous exécutez des commandes internes).

PSkocik
la source
Je ne savais pas que c'était f() (...)autorisé. Y a-t-il d'autres définitions en dehors de {...}et (...)? Dans Bash, je ne suis pas encore dans les autres.
Tomasz
1
@tomas Vous pouvez utiliser la function hw { echo hello world; } syntaxe (inutile ()si vous tapez functionet vous pouvez spécifier des redirections juste après la finale }ou )comme hw(){ echo error; } >&2dedans. C'est à peu près tout.
PSkocik
2
C'est la réponse à laquelle j'ai immédiatement pensé, et elle est absolument correcte. Elle devrait être votée comme la bonne réponse. f()(...)toujours exécuter un propre shell, mais f(){...}pas.
rexkogitans
11
Les fonctions bash NB acceptent toutes les commandes composées, de même foo() [[ x = x ]]qu'une définition de fonction valide. Cependant, si vous regardez la fonction avec, type foovous verrez que c'est toujours du sucre syntaxique pour foo() { [[ x = x ]]; }. Il en va de même pour les fonctions de sous-shell: bar() ( : )devient bar() { ( : ); }.
kojiro
1
@kojiro nice +1. ne savait pas cela
PSkocik
9

La commande en question de cet exemple ressemble à:

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

L'exemple indique plus tard:

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

Étant charitable pour ABS Guide, ce qu'ils voulaient apparemment écrire, c'est que la fonction s'exécute à l'intérieur d'une substitution de commande et que la commande à l'intérieur d'une substitution de commande s'exécute dans un sous - shell .

John1024
la source
C'est très trompeur. Merci pour votre interprétation.
Tomasz
5
@tomas "très trompeur." Oui très. Contrairement au Guide ABS, le Wiki de Greg est une excellente source d'informations bash avancées.
John1024
1
À votre santé. Quelle est votre opinion sur celui-ci: wiki.bash-hackers.org/start ?
Tomasz
@tomas Je n'ai aucune connaissance directe de celui-là.
John1024
2
@tomas, ... ma propre opinion quant au wiki bash-hackers est que c'est une excellente source. Je ne l'ai pas vécu aussi complètement que j'ai le wiki Wooledge, mais il a tendance à être précis et écrit avec précision.
Charles Duffy