considerare questo script:
#!/bin/bash
main() {
cd /tmp
}
main > /dev/null
echo goodbye
Prima bash esegue la funzione main
, ha bisogno di riorientare il proprio standard output a /dev/null
. Quindi è necessario eseguire la funzione main
. Quindi, prima di eseguire il comando echo
, è necessario ripristinare l'output standard su qualsiasi cosa fosse prima del reindirizzamento.
Ecco come funziona. Per eseguire il reindirizzamento, apre /dev/null
, ottenendo (diciamo) il descrittore di file 3. Quindi duplica il descrittore di file 1 (output standard) al primo fd disponibile ≥ 10, ottenendo (diciamo) 10. Quindi duplica fd 3 (aperto /dev/null
) in fd 1, e chiude fd 3.
seguito, per annullare il reindirizzamento, duplica fd 10 (aperta sullo standard output originale di bash) su fd 1, e chiude fd 10.
Ok , ora torna al tuo copione. Le stesse cose accadono quando lo script dice main >/dev/null
, quindi mentre main
è in esecuzione, fd 10 è aperto sullo standard output della shell, che è la fine scrivibile della pipe su cat
.
Quando il vostro main
dice do_sth >/dev/null &
, la shell si biforca. La shell figlio eredita fd 10, quindi sia la shell genitore che quella secondaria hanno fd 10 aperto sulla pipe. (Si noti che la shell sa che non ha bisogno di salvare il suo standard di uscita qui a causa della &
rendendolo forchetta.)
Quando la shell bambino, in do_sth
, corre sleep
, si biforca per eseguire sleep
e attende sleep
per uscire. Quindi il guscio del bambino si blocca per cinque secondi, e durante quel periodo ha aperto fd 10 sulla parte scrivibile della pipa.
Il cat
processo non legge EOF sull'estremità leggibile del tubo fino a quando tutti i descrittori di file sull'estremità scrivibile sono chiuse, cosa che non avviene fino a quel shell termina bambino, che non avviene fino sleep
uscite.