GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Werden Nicht-Umgebungsvariablen an die durch Befehlssubstitution aufgerufene Subshell übergeben?

Bash-Handbuch sagt:

Befehlssubstitution, in Klammern gruppierte Befehle und asynchrone Befehle werden in einer Subshell-Umgebung aufgerufen, die ein Duplikat der Shell-Umgebung ist,
außer dass Traps, die von der Shell abgefangen werden, auf die Werte zurückgesetzt werden, die die Shell von ihrer übergeordneten Shell geerbt hat Aufruf.

In diesem Beispiel b ist keine Umgebungsvariable, also b existiert nicht in der Subshell, die durch Befehlssubstitution erstellt wurde. Warum ist dann c den Wert von b zugewiesen durch Befehlsersetzung? Liegt es daran, dass die Parametererweiterung für $b erfolgt? im Shell-Prozess, bevor Sie eine Subshell erstellen, um echo 1 auszuführen ?

$ b=1
$ c=$(echo $b)
$ echo $c
1

Akzeptierte Antwort:

Nein, die Subshell wurde zuerst erstellt.

Eine Shell-Ausführungsumgebung enthält Shell-Parameter, die durch Variablenzuweisungen und Umgebungsvariablen festgelegt werden. Eine Subshell-Umgebung wurde durch Duplizieren der Shell-Umgebung erstellt, sodass sie alle Variablen der aktuellen Shell-Umgebung enthält.

Siehe Beispiel:

$ b=1
$ c=$(b=2; echo "$b")
$ echo "$c"
2

Die Ausgabe ist 2 statt 1 .

Eine durch Befehlssubstitution erstellte Subshell-Umgebung unterscheidet sich von einer Shell-Umgebung, die durch Aufrufen der ausführbaren Shell-Datei erstellt wurde.

Wenn Sie die Shell aufrufen als:

$ bash -c :

Die aktuelle Shell hat execve() verwendet, um einen neuen Shell-Prozess zu erstellen, etwa so:

execve("/bin/bash", ["bash", "-c", ":"], [/* 64 vars */]) = 0

das letzte an execve übergebene Argument enthält alle Umgebungsvariablen.

Aus diesem Grund müssen Sie die Variablen exportieren, um sie in die Umgebungsvariablen zu verschieben, die in anschließend ausgeführten Befehlen enthalten sind:

$ a=; export a
$ strace -e execve bash -c :
execve("/bin/bash", ["bash", "-c", ":"], [/* 65 vars */]) = 0
+++ exited with 0 +++

Beachten Sie, dass sich die Umgebungsvariablen von 64 auf 65 ändern. Und Variablen, die nicht exportiert werden, werden nicht an die neue Shell-Umgebung übergeben:

$ a=; b=; export a
$ strace -e execve bash -c :
execve("/bin/bash", ["bash", "-c", ":"], [/* 65 vars */]) = 0
+++ exited with 0 +++

Beachten Sie, dass die Umgebungsvariablen immer noch 65 sind.

Bei der Befehlsersetzung verwendete die Shell fork(), um einen neuen Shell-Prozess zu erstellen, der einfach die aktuelle Shell-Umgebung kopierte – die sowohl Variablensätze als auch Umgebungsvariablen enthält.


Linux
  1. Der Sinn des externen Befehls „cd“?

  2. Der Unterschied in der Verwendung zwischen Shell-Variablen und Umgebungsvariablen?

  3. Welches sind die speziellen Parameter/Variablen der (Bash-)Shell?

  4. Wie werden Klammern in der Befehlszeile interpretiert?

  5. Verwenden von Umgebungsvariablen im cURL-Befehl - Unix

Platzieren Klammern den Befehl wirklich in einer Subshell?

Was ist der Unterschied zwischen dem Abrufen der Befehlsausgabe mit "command" und $(command) in der Shell??

Linux – Sind Umgebungsvariablen für nicht privilegierte Benutzer unter Linux sichtbar?

Was sind die verschiedenen Arten von Shells in Linux?

Variablen in der Bash-Shell unter Linux verstehen

useradd vs. adduser:Was sind die Unterschiede?