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 var
zmienną, chociaż nie jest eksportowana, aw ./file
przypadku, 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ć, strace
aby 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 ./file
powinien mieć tę samą przestrzeń adresową procesu nadrzędnego, więc dlaczego w ()
przypadku jest varible widoczne podpowłoce i tym samym nie stanie na ./file
razie, chociaż te same argumenty są oparte na funkcji systemowej clone?
Odpowiedzi:
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./file
piszesz, wykonywane jest nowe polecenie, np. Nowa powłoka; w danych wyjściowych strace spójrz naexecve
i podobne) . Zasadniczo jest to tylko kopia (z pewnymi udokumentowanymi różnicami).Uwaga: nie dotyczy to bash; dotyczy to każdej powłoki.
źródło
-f
opcjistrace
śledzenia dzieci? Jest to konieczne do znalezienia egzekucji.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
fork
jest szczególnym przypadkiem bardziej ogólnegoclone
wywołania systemowego, które zaobserwowano wstrace
dzienniku. Dziecko uruchamia część skryptu powłoki. Proces potomny nazywa się podpowłoką . Najbardziej bezpośrednim takim konstruktem jestcommand1 &
:command1
dział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 potokicommand3 | command4
(command3
działa w podpowłoce,command4
dział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ąBASHPID
na identyfikator procesu potomnego.Po uruchomieniu
./file
wykonuje zewnętrzne polecenie. Po pierwsze, powłoka uruchamia proces potomny; następnie ten proces potomny wykonuje (za pomocąexecve
wywołania systemowego) plik wykonywalny./file
. Proces potomny dziedziczy atrybuty procesów jego rodziców: środowisko, bieżący katalog itp. Wexecve
wywoł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 przetrwaexecve
.źródło