GNU/Linux >> Znalost Linux >  >> Linux

Proč je proměnná viditelná v podslupce?

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.


Linux
  1. Proč má uživatel mysql bash shell v /etc/passwd?

  2. Proč /bin/sh ukazuje na /bin/dash a ne /bin/bash?

  3. Proč nefunguje find -exec mv {} ./target/ +?

  1. unix:///var/run/supervisor.sock žádný takový soubor

  2. echo nebo print /dev/stdin /dev/stdout /dev/stderr

  3. Proč jsou < nebo > vyžadovány pro použití /dev/tcp

  1. Jak Linux zpracovává více po sobě jdoucích oddělovačů cest (/home////username///soubor)?

  2. Bash =~ Regex A Https://regex101.com/?

  3. Proč potřebujete umístit #!/bin/bash na začátek souboru skriptu?