Dlaczego zmienna jest widoczna w podpowłoce?


18

W Learning Bash Book wspomniano, że podpowłoka odziedziczy tylko zmienne środowiskowe i deskryptory plików itp. Oraz że nie odziedziczy zmiennych, które nie są eksportowane:

$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var

$

Jak wiem, powłoka utworzy dwie podpowłoki dla ()i dla ./file, ale dlaczego w takim ()przypadku podpowłoka identyfikuje varzmienną, chociaż nie jest eksportowana, aw ./fileprzypadku, gdy jej nie identyfikuje?

# Strace for () 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25617
# Strace for ./file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25631

Próbowałem użyć, straceaby dowiedzieć się, jak to się dzieje i, co zaskakujące, odkryłem, że bash użyje tych samych argumentów dla wywołania systemowego klonowania, więc oznacza to, że zarówno rozwidlony proces w, jak ()i ./filepowinien mieć tę samą przestrzeń adresową procesu nadrzędnego, więc dlaczego w ()przypadku jest varible widoczne podpowłoce i tym samym nie stanie na ./filerazie, chociaż te same argumenty są oparte na funkcji systemowej clone?


vinc17 mówi prawdę, nawet jeśli dostajesz pstree, gdy masz podpowłokę, wierzysz w tę sprawę.
PersianGulf

Odpowiedzi:


15

Learning Bash Book jest błędna. Podkładki dziedziczą wszystkie zmienne. Nawet $$(PID oryginalnej powłoki) zostaje zachowany. Powodem jest to, że dla podpowłoki powłoka po prostu rozwidla się i nie wykonuje nowej powłoki (wręcz przeciwnie, gdy ./filepiszesz, wykonywane jest nowe polecenie, np. Nowa powłoka; w danych wyjściowych strace spójrz na execvei podobne) . Zasadniczo jest to tylko kopia (z pewnymi udokumentowanymi różnicami).

Uwaga: nie dotyczy to bash; dotyczy to każdej powłoki.


Ok, ale próbowałem teraz uruchomić strace na powłoce i próbowałem wykonać plik ./, ale nie mogę znaleźć żadnego wywołania dla exec, więc przestrzeń adresowa powinna być taka sama dla obu procesów, więc jak to wyjaśnić?
user3718463

@ user3718463 Czy korzystałeś z -fopcji straceśledzenia dzieci? Jest to konieczne do znalezienia egzekucji.
vinc17

tak, wymyśliłem to dzięki bardzo, brakowało mi opcji -f, więc nie mogę znaleźć wywołania exec sys
user3718463

16

Ty lub książka mylicie podpowłokę z podprocesem, który jest powłoką.

Niektóre konstrukcje powłoki powodują, że powłoka wywołuje proces potomny. Pod Linuksem forkjest szczególnym przypadkiem bardziej ogólnego clonewywołania systemowego, które zaobserwowano w stracedzienniku. Dziecko uruchamia część skryptu powłoki. Proces potomny nazywa się podpowłoką . Najbardziej bezpośrednim takim konstruktem jest command1 &: command1działa w podpowłoce, a kolejne polecenia są uruchamiane w powłoce nadrzędnej. Inne konstrukcje, które tworzą podpowłokę, obejmują podstawianie poleceń $(command2)i potoki command3 | command4( command3działa w podpowłoce, command4działa w podpowłoce w większości powłok, ale nie w ksh ani zsh).

Podpowłoka jest kopią procesu nadrzędnego, więc ma nie tylko te same zmienne środowiskowe, ale także wszystkie te same definicje wewnętrzne: zmienne (w tym $$identyfikator procesu pierwotnego procesu powłoki), funkcje, aliasy, opcje itp. Przed wykonaniem kodu w podpowłoce bash ustawia zmienną BASHPIDna identyfikator procesu potomnego.

Po uruchomieniu ./filewykonuje zewnętrzne polecenie. Po pierwsze, powłoka uruchamia proces potomny; następnie ten proces potomny wykonuje (za pomocą execvewywołania systemowego) plik wykonywalny ./file. Proces potomny dziedziczy atrybuty procesów jego rodziców: środowisko, bieżący katalog itp. W execvewywołaniu gubi się wewnętrzne aspekty aplikacji : nieeksportowane zmienne, funkcje itp. To pojęcia bash, o których jądro nie wie, i są zgubione, gdy bash wykonuje inny program. Nawet jeśli ten inny program okazuje się skryptem bash, jest on wykonywany przez nową instancję bash, która nie wie ani nie obchodzi, że jego proces nadrzędny jest również instancją bash. Zatem zmienna powłoki (zmienna nieeksportowana) nie przetrwa execve.


Ta odpowiedź wyjaśniła mi całkiem sporo rzeczy. Jedyne, czego nie rozumiem, to zdanie w drugim akapicie: „Dziecko uruchamia część skryptu powłoki”. Do jakiego skryptu powłoki odwołuje się?
flow2k

@ flow2k Skrypt (tj. program), który interpretuje powłoka.
Gilles „SO- przestań być zły”
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.