Czy nawiasy naprawdę umieszczają polecenie w podpowłoce?


94

Z tego, co przeczytałem, umieszczenie polecenia w nawiasach powinno uruchamiać je w podpowłoce, podobnie jak uruchamianie skryptu. Jeśli to prawda, jak widzi zmienną x, jeśli x nie jest eksportowane?

x=1

Uruchomienie (echo $x)w wierszu poleceń powoduje 1

Uruchomienie echo $xw skrypcie nie daje niczego, zgodnie z oczekiwaniami

Odpowiedzi:


134

Podpowłoka zaczyna się jako prawie identyczna kopia oryginalnego procesu powłoki. Pod maską powłoka wywołuje forkwywołanie systemowe 1 , które tworzy nowy proces, którego kod i pamięć są kopiami 2 . Po utworzeniu podpowłoki istnieje bardzo niewiele różnic między nią a jej elementem nadrzędnym. W szczególności mają te same zmienne. Nawet $$specjalna zmienna zachowuje tę samą wartość w podpowłokach: jest to identyfikator procesu oryginalnej powłoki. Podobnie $PPIDjest PID rodzica oryginalnej powłoki.

Kilka powłok zmienia kilka zmiennych w podpowłoce. Bash ustawia BASHPIDna PID procesu powłoki, który zmienia się w podpowłoce. Bash, zsh i mksh umożliwiają $RANDOMuzyskanie różnych wartości w rodzicu i podpowłoce. Ale oprócz wbudowanych specjalnych przypadków takich jak te, wszystkie zmienne mają taką samą wartość w podpowłoce jak w oryginalnej powłoce, ten sam status eksportu, ten sam status tylko do odczytu itp. Wszystkie definicje funkcji, definicje aliasów, opcje powłoki i inne ustawienia są również dziedziczone.

Podkładka utworzona przez (…)ma takie same deskryptory plików jak jej twórca. Niektóre inne sposoby tworzenia podpowłoki modyfikują niektóre deskryptory plików przed wykonaniem kodu użytkownika; na przykład lewa strona rury biegnie w podpowłoce 3 ze standardowym wyjściem podłączonym do rury. Podpowłoka również zaczyna się od tego samego bieżącego katalogu, tej samej maski sygnału itp. Jednym z kilku wyjątków jest to, że podpowłoki nie dziedziczą pułapek niestandardowych: ignorowane sygnały ( ) pozostają ignorowane w podpowłoce, ale inne pułapki ( SYGNAŁ ) są resetowane do domyślnej akcji 4 .trap '' SIGNALtrap CODE

Zatem podpowłoka różni się od wykonywania skryptu. Skrypt jest osobnym programem. Ten osobny program może być przypadkowo również skryptem, który jest wykonywany przez tego samego interpretera, co rodzic, ale ten przypadek nie zapewnia osobnemu programowi żadnej szczególnej widoczności wewnętrznych danych rodzica. Nieeksportowane zmienne są danymi wewnętrznymi, więc gdy wykonywany jest interpreter skryptu powłoki potomnej , nie widzi tych zmiennych. Eksportowane zmienne, tj. Zmienne środowiskowe, są przekazywane do wykonywanych programów.

A zatem:

x=1
(echo $x)

wypisuje, 1ponieważ podpowłoka jest replikacją powłoki, która ją zrodziła.

x=1
sh -c 'echo $x'

zdarza się, że uruchamia powłokę jako proces potomny powłoki, ale xw drugiej linii nie ma więcej połączenia z xdrugą linią niż w

x=1
perl -le 'print $x'

lub

x=1
python -c 'print x'

1 Wyjątkiem jest ksh93powłoka, w której rozwidlenie jest zoptymalizowane i emulowana jest większość jego skutków ubocznych.
2 Semantycznie są kopiami. Z punktu widzenia implementacji dzieje się dużo udostępniania.
3 Po prawej stronie zależy to od skorupy.
4 Jeśli to przetestujesz, zauważ, że takie rzeczy$(trap) mogą zgłaszać pułapki oryginalnej powłoki. Zauważ też, że wiele pocisków ma błędy w narożnych skrzyniach z pułapkami. Na przykład ninjalj zauważa, że ​​od wersji bash 4.3 bash -x -c 'trap "echo ERR at \$BASH_SUBSHELL \$BASHPID" ERR; set -E; false; echo one subshell; (false); echo two subshells; ( (false) )'uruchamia ERRpułapkę z zagnieżdżonej podpowłoki w przypadku „dwóch podpowłok”, ale nie ERRpułapkę z podpowłoki pośredniej - set -Eopcja powinna propagowaćERRpułapka na wszystkie podpowłoki, ale podpowłoka pośrednia jest zoptymalizowana, więc nie ma jej, aby uruchomić ERRpułapkę.


2
@Kusalananda No. ( x=out; (x=in; echo $x))
Gilles

2
@ flow2k Jest to kolejność ekspansji dla rzeczy dziejących się na tym samym poziomie. Ale musisz również rozważyć, w jaki sposób ekspansja miesza się z ewaluacją. Gdy ekspansja wymaga oceny zagnieżdżonej konstrukcji, najpierw analizowana jest konstrukcja wewnętrzna. Na przykład, aby ocenić echo $(x=2; echo $x), fragment $(x=2; echo $x)należy rozszerzyć. Wymaga to oceny polecenia x=2; echo $x. Rozszerzenie $xnastępuje podczas tej oceny, po dokonaniu oceny części x=2.
Gilles

2
@ flow2k Nie ma kolejności między rozszerzaniem parametrów a zastępowaniem poleceń. Zauważ, że to zdanie używa średników do oddzielenia kroków interpretacji, ale interpretacja parametrów i podstawianie poleceń znajdują się w tej samej klauzuli rozdzielanej średnikami (tak, jest subtelna). Kolejność ma znaczenie, gdy jedna z części ma efekt uboczny, który wpływa na drugą część, np. (Z xnieustawionym) echo $(echo foo >somefile)${x-$(cat somefile)}lub echo $(echo $x),${x=1}.
Gilles

1
@Gilles; Jestem zdezorientowany. Jeśli podpowłoka różni się od wykonywania skryptu, dlaczego mówi się, że: Uruchomienie skryptu powłoki uruchamia nowy proces, podpowłokę. ? Ponadto należy utworzyć środowisko podpowłoki jako duplikat środowiska powłoki . Dlatego plik ./ zostanie wykonany w środowisku podpowłoki, dlatego powinien dziedziczyć parametry powłoki ustawione przez przypisanie zmiennej.
haccks

2
@haccks Definicja w ABS jest przybliżeniem i niezbyt dobrym. Przykłady są dobre, ale pierwsze dwa wiersze tej strony są tak uproszczone, że się mylą. Uruchomienie skryptu z innego skryptu uruchamia nowy proces, który nie jest podpowłoką. W SUS definicje są poprawne (ale nie zawsze bardzo łatwe do zrozumienia). ./filenie jest wykonywany w podpowłoce. Zobacz także unix.stackexchange.com/q/261638 i unix.stackexchange.com/a/157962
Gilles

15

Oczywiście tak, jak mówi cała dokumentacja, nawiasowe polecenie jest uruchamiane w podpowłoce.

Podkładka dziedziczy kopię wszystkich zmiennych rodzica. Różnica polega na tym, że wszelkie zmiany wprowadzone w podpowłoce nie są również wprowadzane w obiekcie nadrzędnym.

Strona podręcznika ksh sprawia, że ​​jest to trochę jaśniejsze niż strona bash:

man ksh:

Polecenie w nawiasie okrągłym jest wykonywane w podpowłoce bez usuwania nieeksportowanych zmiennych.

man bash:

(lista)

lista jest wykonywana w środowisku podpowłoki (patrz ŚRODOWISKO WYKONYWANIA POLECEŃ poniżej). Zmienne przypisania i wbudowane polecenia, które wpływają na środowisko powłoki, nie pozostają aktywne po zakończeniu polecenia.

ŚRODOWISKO WYKONANIA POLECEŃ

Powłoka ma środowisko wykonawcze, które składa się z: [...] parametrów powłoki, które są ustawiane przez przypisanie zmiennych [...].
Podstawianie poleceń, polecenia zgrupowane w nawiasach oraz polecenia asynchroniczne są wywoływane w środowisku podpowłoki, które jest duplikatem środowiska powłoki, [...]


3
Należy to skontrastować z tym When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate execution environment that consists of the following., który zawiera element: · shell variables and functions marked for export, along with variables exported for the command, passed in the environment(z tej samej man bashsekcji), który wyjaśnia, dlaczego echo $xskrypt nie drukuje nic, jeśli xnie jest eksportowany.
Johan E
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.