Kniha Learning Bash Book uvádí, že subshell zdědí pouze proměnné prostředí a deskriptory souborů atd., a že nedědí proměnné, které se neexportují:
$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var
$
Jak vím, shell vytvoří dvě podskořápky pro ()
a pro ./file
, ale proč v ()
případ identifikuje subshell var
proměnná, i když není exportována a v ./file
případ, že to neidentifikovalo?
# 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
Zkusil jsem použít strace
abych zjistil, jak se to stane, a překvapivě jsem zjistil, že bash použije stejné argumenty pro systémové volání klonování, takže to znamená, že oba rozvětvený proces v ()
a ./file
by měl mít stejný adresní prostor procesu jako rodič, tak proč v ()
case je proměnná viditelná pro podshell a totéž se nestane pro ./file
case, ačkoli stejné argumenty jsou založeny na systémovém volání klon?
Přijatá odpověď:
The Learning Bash Book je špatně. Subshells dědí všechny proměnné. Dokonce $$
(PID původního shellu) je zachován. Důvodem je to, že u subshell se shell pouze rozvětví a neprovede nový shell (naopak, když napíšete ./file
je proveden nový příkaz, např. nová skořápka; ve výstupu strace se podívejte na execve
a podobně). V podstatě je to tedy jen kopie (s některými zdokumentovanými rozdíly).
Poznámka:toto není specifické pro bash; to platí pro jakýkoli shell.