El libro Learning Bash menciona que una subcapa heredará solo variables de entorno y descriptores de archivos, etc., y que no heredará variables que no se exporten:
$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var
$
Como sé, el shell creará dos subshells para ()
y para ./file
, pero ¿por qué en el ()
caso, la subcapa identifica el var
variable aunque no se exporta y en el ./file
caso de que no lo identificara?
# 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
Traté de usar strace
para descubrir cómo sucede esto y, sorprendentemente, descubrí que bash usará los mismos argumentos para la llamada del sistema de clonación, lo que significa que tanto el proceso bifurcado en ()
y ./file
debe tener el mismo espacio de direcciones de proceso del padre, entonces ¿por qué en el ()
case es la variable visible para el subshell y no sucede lo mismo para el ./file
caso, aunque los mismos argumentos se basan en la llamada del sistema de clonación?
Respuesta aceptada:
El libro Learning Bash está mal. Las subcapas heredan todas las variables. Incluso $$
(el PID del shell original) se mantiene. La razón es que para un subshell, el shell simplemente se bifurca y no ejecuta un nuevo shell (por el contrario, cuando escribe ./file
, se ejecuta un nuevo comando, p. una nueva concha; en la salida de strace, mire execve
y similares). Entonces, básicamente, es solo una copia (con algunas diferencias documentadas).
Nota:esto no es específico de bash; esto es cierto para cualquier shell.