2015-10-02 12 views
7

Ho uno script bash: my.shPerché il mio script di bash è bloccato?

#!/bin/bash 

do_sth() 
{ 
    sleep 5 
} 

main() 
{ 
    do_sth >/dev/null & 
    echo do sth in background ... 
} 

if [ "$1" = "1st_way" ]; then 
    main 
elif [ "$1" = "2nd_way" ]; then 
    main >/dev/null 
fi 

I seguenti comando restituisce immediatamente

./my.sh 1st_way | cat 

Ma, i seguenti blocchi di comando per 5 secondi

./my.sh 2nd_way | cat 

Mi chiedo perché stia bloccando per 5 secondi nel 2o modo.

risposta

5

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.

Problemi correlati