Werden Funktionen in Bash als Unterprozesse ausgeführt?

28

In Advanced Bash-Scripting Guide , in Beispiel 27-4 , 7. Zeile von unten, habe ich Folgendes gelesen:

Eine Funktion wird als Unterprozess ausgeführt.

Ich habe einen Test in Bash gemacht und es scheint, dass die obige Aussage falsch ist.

Suchanfragen auf dieser Site, Bash Man, und meine Suchmaschine bringen kein Licht.

Haben Sie die Antwort und möchten sie erklären?

Tomasz
quelle
12
Wie bereits erwähnt, ist dieser Leitfaden äußerst irreführend. Ich empfehle stattdessen den Wooledge Bash Guide .
Wildcard

Antworten:

36

Das Advanced Bash-Scripting Guide ist nicht immer zuverlässig, und seine Beispielskripte enthalten veraltete Vorgehensweisen wie die Verwendung der effektiv veralteten Backticks für die Befehlsersetzung, dh `command`anstatt $(command).

In diesem speziellen Fall ist es offensichtlich falsch.

Der Abschnitt über Shell-Funktionen im (kanonischen) Bash-Handbuch besagt dies definitiv

Shell-Funktionen werden im aktuellen Shell-Kontext ausgeführt. Es wird kein neuer Prozess erstellt, um sie zu interpretieren.

Anthony G - Gerechtigkeit für Monica
quelle
10
"Advanced Bash-Scripting Guide ist im Allgemeinen unzuverlässig" Sehr wahr.
John1024
1
Können Sie Hinweise geben, um Ihren ersten Satz zu unterstützen?
Will Vousden
5
@WillVousden wie würde eine Referenz hier aussehen? Eine Reihe von Beispielen für die technischen Mängel des Leitfadens? Ein Dokument, in dem Experten der Bash-Community zuvor festgestellt haben, dass es unzuverlässig ist? Wäre es hilfreich, wenn ein Stackoverflow-Mitglied mit einem goldenen Abzeichen in Bash nur in einem Kommentar zustimmt? : p
kojiro
3
@WillVousden Ich glaube nicht, dass das, was du willst, in zuverlässiger Form existiert. Mendel Cooper hat Probleme mit dem Handbuch in der Vergangenheit aktualisiert und behoben, aber es gibt keinen öffentlichen Bug-Tracker oder eine Liste von Errata. (Vielleicht ist das die schlimmste Aussage, die ich machen kann.) Wenn wir also einen (wahrgenommenen oder echten) Fehler finden, können wir dem Autor nur eine E-Mail schreiben und auf das Beste hoffen.
Kojiro
3
@WillVousden, ... wenn Sie einen wollen Geschichte davon , wie lange soll der Konsens im freenode #bash Kanal war , dass der ABS vermieden werden, siehe wooledge.org/~greybot/meta/abs - das zweite Feld in jeder Zeile ist der Zeitstempel und der erste ist der Benutzername; Ich hoffe, dass die Behauptung, dass es sich bei den fraglichen Benutzernamen um sehr angesehene Personen handelt, ausreicht.
Charles Duffy
32

Funktionen für geschweifte Klammern werden innerhalb des aufrufenden Shell-Prozesses ausgeführt, es sei denn, sie benötigen eine eigene Subshell:

  • wenn Sie sie im Hintergrund mit ausführen &
  • wenn Sie sie als Verknüpfung in einer Pipeline ausführen

Umleitungen oder zusätzliche Umgebung Variablen erzwingen keine neue Subshell:

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

Wenn Sie die Funktion mit Klammern anstelle von Kurven definieren:

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

Es wird immer in einem neuen Prozess ausgeführt.

Die $()Befehlsersetzung erstellt auch immer Prozesse in bash (aber nicht in ksh, wenn Sie eingebaute Befehle ausführen).

PSkocik
quelle
Ich wusste nicht, f() (...)ist erlaubt. Gibt es neben {...}und noch weitere Definitionen (...)? In Bash stehe ich noch nicht auf andere.
Tomasz
1
@tomas Du kannst die function hw { echo hello world; } Syntax verwenden (keine Notwendigkeit, ()wenn du etwas eingibst , functionund du kannst Umleitungen direkt nach dem Finale }oder )wie in angeben hw(){ echo error; } >&2. Das war's auch schon.
PSkocik
2
Dies ist die Antwort, über die ich sofort nachgedacht habe und die absolut richtig ist. Es sollte als die richtige Antwort gewählt werden. f()(...)Führe immer eine eigene Shell aus, während f(){...}dies nicht der Fall ist.
Rexkogitans
11
NB Bash-Funktionen akzeptieren jeden zusammengesetzten Befehl, daher foo() [[ x = x ]]ist dies auch eine gültige Funktionsdefinition. Wenn Sie jedoch die Funktion mit betrachten, werden type fooSie feststellen, dass dies immer noch syntaktischer Zucker ist foo() { [[ x = x ]]; }. Gleiches gilt für Subshell-Funktionen: bar() ( : )wird bar() { ( : ); }.
Kojiro
1
@kojiro schön +1. wusste das nicht
PSkocik
9

Der fragliche Befehl aus diesem Beispiel sieht folgendermaßen aus:

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

Das Beispiel später besagt:

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

Als gemeinnützige Organisation von ABS Guide wollten sie anscheinend schreiben, dass die Funktion in einer Befehlsersetzung ausgeführt wird und der Befehl in einer Befehlsersetzung in einer Subshell ausgeführt wird .

John1024
quelle
Das ist sehr irreführend. Vielen Dank für Ihre Interpretation.
Tomasz
5
@tomas "sehr irreführend." Ja sehr. Im Gegensatz zum ABS-Leitfaden ist Gregs Wiki eine hervorragende Quelle für erweiterte Bash-Informationen.
John1024
1
Prost. Was ist deine Meinung dazu: wiki.bash-hackers.org/start ?
Tomasz
@tomas Ich habe keine Kenntnisse aus erster Hand.
John1024
2
@tomas, ... Meiner Meinung nach ist das Bash-Hacker-Wiki eine exzellente Quelle. Ich habe es nicht so ausführlich durchgearbeitet wie das Wooledge-Wiki, aber es ist in der Regel genau und präzise geschrieben.
Charles Duffy