Ci sono questi due nomi:una subshell e una child-shell .
Sì, un processo figlio verrà avviato da uno di questi:
sh -c 'echo "Hello"'
( echo "hello" )
echo "$(echo "hello")
echo "hello" | cat
Sono tutti equivalenti e condividono lo stesso nome? Condividono tutti le stesse proprietà?
POSIX ha questa definizione:
Un ambiente di esecuzione della shell è costituito da ….
Ma l'ultimo paragrafo del link sopra ha questo:
Un ambiente subshell deve essere creato come duplicato dell'ambiente shell, tranne per il fatto che le trappole di segnale che non vengono ignorate devono essere impostate sull'azione predefinita.
E in particolare:
La sostituzione dei comandi, i comandi raggruppati tra parentesi e gli elenchi asincroni devono essere eseguiti in un ambiente subshell. Inoltre, ogni comando di una pipeline multi-comando si trova in un ambiente subshell; ….
Il sh -c 'echo "Hello"'
non è incluso lì, dovrebbe essere chiamata anche una subshell?
Risposta accettata:
Una subshell duplica la shell esistente. Ha le stesse variabili¹, le stesse funzioni, le stesse opzioni, ecc. Sotto il cofano, viene creata una subshell con il fork
chiamata di sistema²; il processo figlio continua a fare ciò che ci si aspetta da esso mentre il genitore attende (ad esempio, $(…)
) o continua la sua vita (ad es. … &
) o in altro modo fa ciò che ci si aspetta da esso (ad esempio, … | …
).
sh -c …
non crea una subshell. Lancia un altro programma. Quel programma sembra essere una shell, ma è solo una coincidenza. Il programma potrebbe anche essere una shell diversa (ad esempio, se esegui sh -c …
da bash e sh
is dash), ovvero un programma completamente diverso che ha somiglianze significative nel suo comportamento. Sotto il cofano, lanciando un comando esterno (sh
o qualsiasi altro) chiama il fork
chiamata di sistema e quindi execve
chiamata di sistema per sostituire il programma shell nel sottoprocesso da un altro programma (qui sh
).
¹ Compreso $$
, ma escludendo alcune variabili specifiche della shell come bash e BASHPID
di mksh .
² Almeno, questa è l'implementazione tradizionale e consueta. Le shell possono ottimizzare il fork se possono imitare il comportamento in caso contrario.
Pagine man rilevanti:fork(2), execve(2).