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 sleep
comando no se ejecuta en un shell separado (como lo determina pstree
otro terminal). Sin embargo, en el fragmento de código B, el segundo sleep
comando 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
fork
y se crea un proceso hijo (para ejecutar comandos externos) llamandofork + exec
. Pero su primer párrafo sugiere que tambiénfork + exec
se requiere subshell. ¿Qué me estoy equivocando aquí?fork
+exec
no se llama para la subshell, se llama para el comando externo. Sin ninguna optimización, hay unafork
llamada 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 queexec
dependa de si el subshell tiene algún comando externo para ejecutar, mientras que en caso de ejecutar cualquier comando externo debe haberlofork + exec
.date
en 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
sleep
ejecute 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.sleep
que no parece estar integrado, esperaría que la segundasleep
llamada en ambos fragmentos se ejecute en un subproceso del proceso de subshell.$BASHPID
variable. 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 bash
lí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