Parece que no entiendo la regla de Bash para crear una subshell. Pensé que los paréntesis siempre crean una subshell, que se ejecuta como su propio proceso.
Sin embargo, este no parece ser el caso. En el fragmento de código A (a continuación), el segundo sleepcomando no se ejecuta en un shell separado (como lo determina pstreeotro terminal). Sin embargo, en el fragmento de código B, el segundo sleepcomando se ejecuta en un shell separado. La única diferencia entre los fragmentos es que el segundo fragmento tiene dos comandos entre paréntesis.
¿Podría alguien explicar la regla de cuándo se crean subcapas?
CÓDIGO SNIPPET A:
sleep 5
(
sleep 5
)
CÓDIGO SNIPPET B:
sleep 5
(
x=1
sleep 5
)
fuente

forky se crea un proceso hijo (para ejecutar comandos externos) llamandofork + exec. Pero su primer párrafo sugiere que tambiénfork + execse requiere subshell. ¿Qué me estoy equivocando aquí?fork+execno se llama para la subshell, se llama para el comando externo. Sin ninguna optimización, hay unaforkllamada para la subshell y otra para el comando externo. Agregué una descripción detallada del flujo a mi respuesta.(...)(en el caso base), puede o no haber una llamada para queexecdependa de si el subshell tiene algún comando externo para ejecutar, mientras que en caso de ejecutar cualquier comando externo debe haberlofork + exec.dateen un shell?strace -f -e clone,execve,write bash -c 'date'ystrace -f -e clone,execve,write bash -c 'date; true'De la Guía de programación avanzada de Bash :
"En general, un comando externo en un script bifurca un subproceso, mientras que un comando interno Bash no lo hace. Por esta razón, los comandos internos se ejecutan más rápidamente y usan menos recursos del sistema que sus equivalentes de comandos externos".
Y un poco más abajo:
"Una lista de comandos incrustada entre paréntesis se ejecuta como un subshell".
Ejemplos:
Ejemplo que usa el código OP (con sueños más cortos porque soy impaciente):
La salida:
fuente
sleepejecute en una subshell (tal vez en el proceso de la subshell ya que es una función incorporada, en lugar de un subproceso de la subshell). Sin embargo, en cualquier caso, hubiera esperado que existiera una subshell, es decir, un subproceso Bash bajo el proceso Bash principal. Para el fragmento B anterior, este no parece ser el caso.sleepque no parece estar integrado, esperaría que la segundasleepllamada en ambos fragmentos se ejecute en un subproceso del proceso de subshell.$BASHPIDvariable. Lamentablemente, la forma en que lo estaba haciendo no le estaba dando toda la historia, creo. Vea mi salida agregada en la respuesta.Una nota adicional a la respuesta de @Gilles.
Como dijo Gilles:
The parentheses always start a subshell.Sin embargo, los números que tiene dicho sub-shell podrían repetirse:
Como puede ver, $$ sigue repitiéndose, y eso es como se esperaba, porque (ejecute este comando para encontrar la
man bashlínea correcta ):Es decir: si el shell no se reinicia, el $$ es el mismo.
O con esto:
El
$$es el ID del shell actual (no el subshell).fuente