Le utility di Linux sono intelligenti quando si eseguono i comandi in pipe?


23

Stavo solo eseguendo alcuni comandi in un terminale e ho iniziato a chiedermi, Unix / Linux prende scorciatoie quando si eseguono comandi in pipe?

Ad esempio, supponiamo che io abbia un file con un milione di righe, le prime 10 delle quali contengono hello world. Se si esegue il comando grep "hello world" file | head, il primo comando si interrompe non appena trova 10 righe o continua a cercare prima l'intero file?


2
Ecco perché gnu grep ha l' -margomento.
Paul Tomblin,

3
Il terminale non ha nulla a che fare con esso. I comandi pipati sono gestiti dalla shell.
Keith Thompson,

@KeithThompson perdona la mia ignoranza, non sono grande in termini di terminologia, non ero sicuro di chiamarlo terminale, shell o riga di comando. Sentiti libero di suggerire modifiche alla mia domanda :)
DisgruntledGoat

Risposte:


30

Una specie di. La shell non ha idea di cosa faranno i comandi che stai eseguendo, collega semplicemente l'output di uno all'input dell'altro.

Se greptrova più di 10 righe che dicono "ciao mondo", allora headavrà tutte e 10 le righe che desidera e chiuderà la pipa. Questo causerà grepl'uccisione di un SIGPIPE, quindi non è necessario continuare la scansione di un file molto grande.


2
Quindi immagino, a causa delle condizioni di gara, grep potrebbe aver già letto l'11 ° o il 12 ° modello, ma probabilmente non il 100 millesimo?
utente sconosciuto

3
Ciò dipende in parte dalla lunghezza delle linee e dalle dimensioni del buffer delle pipe, ma la risposta breve è che grep leggerà una quantità ragionevolmente limitata di dati extra prima di essere ucciso.
Dmckee,

1
@userunknown, esattamente.
psusi,

Bene, non sapevo che fosse successo. Pensavo che grepavrei continuato a inviare l'output in un vuoto, simile a/dev/null
Izkata il

15

Quando un programma tenta di scrivere su una pipe e non vi è alcun processo di lettura da quella pipe, il programma di scrittura riceve un segnale SIGPIPE . L'azione predefinita quando un programma riceve SIGPIPE è di terminare il programma. Un programma può scegliere di ignorare il segnale SIGPIPE, nel qual caso la scrittura restituisce un errore ( EPIPE).

Nel tuo esempio, ecco una sequenza temporale di ciò che accade:

  • I comandi grepe si headavviano in parallelo.
  • grep legge alcuni input, inizia l'elaborazione.
  • Ad un certo punto, grepproduce un primo blocco di output.
  • head legge quel primo pezzo e lo scrive.
  • Supponendo che ci siano abbastanza righe dopo le prime 10 partite (altrimenti greppotrebbe terminare prima), alla fine headavrà stampato il numero desiderato di righe. A questo punto, headesce.
  • A seconda della velocità relativa dei processi grepe head, è greppossibile che alcuni dati siano stati accumulati e non siano stati ancora stampati. Al momento headdell'uscita, greppotrebbe essere in corso la lettura dell'input o l'esecuzione di elaborazioni interne, nel qual caso continuerà a farlo.
  • Presto grepscriverà i dati che vengono elaborati. A quel punto, riceverà un SIGPIPE e morirà.

È probabile che grepelaborerà un input un po 'più di quanto strettamente necessario, ma in genere solo pochi kilobyte:

  • headin genere viene letto in blocchi di pochi kilobyte (perché è più efficiente rispetto all'emissione di una readchiamata di sistema per ogni byte - questo comportamento è chiamato buffering), quindi il resto dell'ultimo pezzo dopo l'ultima riga desiderata viene scartato.
  • Potrebbero esserci dei dati in transito, poiché le pipe hanno un buffer associato gestito dal kernel (spesso 512 byte). Questi dati verranno eliminati.
  • greppotrebbe aver accumulato alcuni dati pronti a diventare un blocco di output (buffer di nuovo). Riceverà SIGPIPE quando sta tentando di svuotare il suo buffer di output.

Tutto sommato, il sistema è progettato con precisione in modo tale che le utility di filtraggio si comportino naturalmente in modo efficiente. I programmi che devono andare avanti quando il loro canale di uscita si spegne devono fare il passo ignorando il segnale SIGPIPE.


3

Sortof, la pipeline funziona in questo modo: esegue prima il primo comando e poi il secondo comando nel tuo caso.

Cioè, dobbiamo A|Bessere il comando dato. Quindi non è sicuro se Ao Binizi per primo. Potrebbero avviarsi esattamente nello stesso momento se ci sono più CPU. Una pipe può contenere una quantità indefinita ma finita di dati.

Se B prova a leggere dalla pipe, ma non sono disponibili dati, Battenderà fino all'arrivo dei dati. Se Bstava leggendo da un disco, Bpotrebbe avere lo stesso problema e attendere il completamento della lettura del disco. Un'analogia più stretta sarebbe leggere da una tastiera. Lì, Bdovrebbe aspettare che un utente digiti. Ma in tutti questi casi, B ha avviato un'operazione di "lettura" e deve attendere fino al termine. Ma se Bè un comando tale che necessita solo di un output parziale di Aallora dopo che un certo punto in cui Bviene raggiunto il livello di input Averrà ucciso da SIGPIPE

Se Atenta di scrivere nella pipe e la pipe è piena, Adeve attendere che un po 'di spazio nella pipe sia libero. Apotrebbe avere lo stesso problema se scrivesse su un terminale. Un terminale ha il controllo del flusso e può moderare il ritmo dei dati. In ogni caso, a A, ha avviato un'operazione di "scrittura" e attenderà il completamento dell'operazione di scrittura.

Ae Bsi comportano come coprocessi, anche se non tutti i coprocessi comunicheranno con una pipa. Nessuno dei due ha il pieno controllo dell'altro.


1
La domanda è: "cosa farebbe A quando B chiudesse il suo lato del tubo?"
enzotib,

2
Non sarebbe un "tubo rotto"?
Patkos Csaba,

1
Se un programma tenta di leggere / scrivere da / verso una pipe chiusa (es head. Esci), si verifica un segnale SIGPIPE nel programma e il comportamento predefinito è di uscire.
Lekensteyn,

Come risponde esattamente alla domanda? Sembra che la risposta di psusi sia più breve e più precisa .
jw013,

1

grepnon ha alcun controllo diretto sulla pipe (sta solo ricevendo dati) e la pipe non ha un controllo diretto sulla grep(sta solo inviando dati) ...

Ciò che grep, o qualsiasi altro programma fa, dipende interamente dalla logica interna di quel programma. Se si dice greptramite le opzioni della riga di comando di fare un'uscita anticipata quando viene trovata , allora lo farà, altrimenti si bloccherà fino alla fine del file cercando il modello ...

Allo stesso modo il Terminale è abbastanza disconnesso dal funzionamento interno grepe dalle shellazioni delle tubazioni ... Il Terminale è fondamentalmente solo un trampolino di lancio e un display di output ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.