2012-04-05 19 views
17

Questo è un comando pipe per la generazione di 10 caratteri della password a caso:Perché questa pipa è stata chiusa?

cat /dev/urandom | base64 | head -c 10 

La mia domanda è cat /dev/urandom | base64 è un flusso di output infinito che non si fermerà da solo. Ma perché l'aggiunta di head -c 10 fa terminare l'intero tubo? Presumo cat, base64 e head sono 3 processi separati, come può head terminare il cat?

risposta

11

Dopo base64 uscite 10 byte, head riceve abbastanza ingressi e uscite. Quando il primo tenta di generare più byte, riceverà SIGPIPE signal e quindi uscirà. Per lo stesso motivo, cat uscirà a turno.

23

head chiude il file di input dopo aver letto la quantità richiesta. quando un tubo viene chiuso da un lato, l'altro lato riceve errori di scrittura; ciò causa la chiusura di base64, che a sua volta causa la chiusura di cat.

+7

Probabilmente vale la pena menzionare che l'unica ragione per cui 'head' ottiene qualsiasi input è che' base64' scrive l'output dopo che ottiene una certa quantità di input, cioè quando il suo buffer è pieno. Se dovesse leggere fino a EOF, leggerà per sempre, e "head" non otterrebbe mai una crepa in nessuna di esse. Quindi una pipeline simile, come 'cat/dev/urandom | somma | head -c 10' si comporterebbe diversamente, poiché 'sum' aspetta EOF. –

+3

s/gets errori di scrittura/riceve SIGPIPE/ –

+1

Il commento di Rob è * estremamente * rilevante. Se il processo eredita un gestore SIGPIPE o ignora SIGPIPE (ad es. Se viene eseguito con il precedente modulo subprocess di python interpreti) e non controlla gli errori di scrittura, non si interromperà. Esiste una differenza * enorme * tra un errore di scrittura e la ricezione di SIGPIPE, ei programmi che ignorano entrambi i problemi sono soggetti a un funzionamento indefinito. –

4

tubazioni funziona collegamento l'output di un processo A all'ingresso di B. La connessione può essere interrotta, quando

  • Un chiude la sua uscita. B otterrà EOF.
  • B chiude il suo input. A riceverà un errore che l'output non è più disponibile quando tenta di scrivere il byte successivo.

Poiché questi due casi sono così comuni, la gestione è stata spostata nel lib standard C.

+0

Grazie, ma cosa significa "la gestione è stata spostata nella libreria C standard"? A e B sono terminati dalla shell invece di rilevare la chiusura di input/output e fermarsi? – Dagang

+0

Quando B chiude il lato del tubo, A riceverà un segnale. Il codice nelle routine I/O della libreria standard c.lib ('fprintf()', 'open()', 'read()', ...) gestisce il segnale e la funzione call restituirà return the errno EPIPE = "Tubo rotto". –

+1

@'AaronDigulla, non sono d'accordo. Non sono a conoscenza di alcuna libreria C che installa un gestore SIGPIPE, né i miei esperimenti lo suggeriscono. In effetti, viene recapitato SIGPIPE che fa sì che qualsiasi programma che non ha installato un gestore (ovvero il 99% di tutti i programmi) venga chiuso. –

Problemi correlati