I sistemi operativi basati su Unix come Linux offrono un approccio unico per unire due comandi sul terminale, con esso si può prendere l’output del primo comando e usarlo come input del secondo comando, questo è il concetto di pipe o |. Le Pipes permettono a due processi separati di comunicare tra loro anche se non sono stati creati per farlo, quindi questo apre una serie infinita di opportunità.
Un semplice esempio è:
ls -l | grep rwxrwxrwx |
Questo comando stampa l’elenco di tutti i file nella directory locale che hanno permesso rwxrwxrwx (o che hanno rwxrwxrwx nel loro nome).
Il modo in cui funziona è che quando la shell vede il simbolo pipe, crea un file temporaneo sul disco rigido. Anche se non ha un nome o una voce di directory, occupa uno spazio fisico sul disco rigido. Poiché sia il terminale che la pipe sono visti come file dal punto di vista del sistema operativo, quello che stiamo dicendo è che il sistema deve utilizzare dei file diversi, invece che lo standard input e lo standard output, ovvero la pipe.
Quindi, con le pipe le informazioni in uscita sono in realtà raffinate ad ogni comando poi passate al comando successivo. Tutto questo funziona grazie ad un paio di caratteristiche dei sistemi Unix:
1. La maggior parte dei comandi UNIX riceve l’input proveniente da stdin e uscita passa in stdout
2. Le pipein UNIX collegano lo stdout del primo comando. allo stdin del secondo comando, e così via se si dispone di pipe multiple.
Altri esempi di pipe sono
ps -ef |grep http|wc -l |
Con questo comando si chiede l’elenco di tutti i processi, quindi filtrare con quello che contiene la stringa “http” e finalmente si chiede il numero di linee.
Così, in breve si conta il numero di processi http in esecuzione.
diff < (cd dir1 && find | sort) <(cd dir2 && find | sort) |
Questo è utile per confrontare due alberi di directory.
Utilizza le funzioni di bash per confrontare (utilizzando diff) l’uscita di due pipe differenti.
tar -cf - . | pv -s $(du -sb . | awk '{print $1}') | gzip > out.tgz |
Quello che succede qui è che diciamo a tar di creare “-c” un archivio di tutti i file nella directory corrente “.” (ricorsivamente) e mandare l’output dei dati su stdout “-f -“. Poi abbiamo specificato la dimensione “-s” per pv di tutti i file nella directory corrente. Il “du -sb .| awk ‘{print $1}'” restituisce il numero di byte nella dir corrente, e lo utilizza con “-s” come parametro per pv. Poi mandiamo a gzip tutto il contenuto e il risultato viene messo in un file out.tgz. In questo modo “pv” conosce la quantità di dati che ancora devono essere elaborati.
Questi sono tutti esempi di pipe Unnamed o anonime .
La pipe esiste solo all’interno del kernel e non può essere acceduta dai processi che la hanno creata, in questi esempi, la shell bash.
L’altro tipo di pipe è la named pipe
Named Pipe
Una named pipe (nota anche come FIFO per il suo comportamento), è persistente nel sistema ed esiste al di là della durata del processo che la utilizza e deve essere cancellata una volta che non è più in uso. I processi in genere si collegano alla named pipe (di solito appare come un file) per eseguire comunicazione tra processi (IPC).
Una named pipe è un vero file nel file system con un permesso particolare, p come prima lettere quando si elencano i file in uan directory con ls -l
ls -l mypipe prw-r--r-- 1 linuxaria linuxaria 0 2011-09-25 21:21 mypipe |
La named pipe agisce come una unnamed pipe ovvero inserite qualcosa in un file da un lato ed esce dall’altro. Da qui il nome FIFO, o First-In-First-Out: la prima cosa che infilate nella pipe è anche la prima ad uscirne.
Se avviate un processo di scrittura verso una named pipe, il processo non terminerà finchè l’informazione che viene scritta non è letta dalla pipe. Se avviate un processo di lettura dalla pipe, il processo aspetterà prima di terminare che non ci sia altro da leggere. Le dimesioni della pipe sono sempre zero — non memorizza dati, si limita ad unire due processi, come il carattere | della shell. Comunque, poichè questa pipe ha un nome, i due processi non devono necessariamente stare sulla riga di comando, nè essere lanciati dallo stesso utente.
Per creare una named pipe è necessario utilizzare il comando mkfifo
sintassi:
mkfifo filename
mkfifo mypipe |
Una volta creata la named pipe si può utilizzarla per condividere le informazioni tra i due processi, come ad esempio:
mkfifo my_pipe cat file > my_pipe gzip -9 -c < my_pipe > out.gz |
In questo esempio si leggere un file con cat
e si dice a cat
di inviare l’output alla named pipe, se si dà questo comando vedrete che la shell andrà in blocco, in attesa che la named pipe sia svuotata, questa è fatto con gzip
, è possibile lanciarlo in un altro terminale, che legge le informazioni dalla named pipe, le comprime e mette il risultato nel file out.gz
Altri esempi di named pipe:
mkfifo my_pipe
script -f my_pipe
cat my_pipe
Questo è utile se si desidera condividere la vostra sessione di terminale con qualcun altro collegato al server Linux su cui si sta lavorando.
In sostanza si inviano tutti i vostri output, avuti a terminale, nella pipe, grazie a script
, mentre l’altro utente può guardare cosa si sta facendo semplicemente con un cat
.
Una volta usata una pipe può essere cancellata come qualsiasi file con il comando rm
.
Capacità della pipe
Una pipe ha una capacità limitata. Se la pipe è piena, una scrittura si blocca o fallirà, a seconda se la pipe è stato aperto in modalità non bloccante. Diverse implementazioni hanno limiti diversi per la capacità di pipe. Le applicazioni non dovrebbero basarsi su una capacità particolare: l’applicazione dovrebbe essere progettata in modo che un processo di lettura utilizzi i dati non appena sono disponibili, in modo che un processo di scrittura non rimanga bloccato.
Nelle versioni di linux precedenti la 2.6.11, la capacità di una pipe era la stessa dimensione della pagina sistema (e.g., 4096 bytes su x86). Da Linux 2.6.11, la capacità delel pipe è diventata di 65536 bytes.
Con kernels recenti (>= 2.6.35), è possibile modificare le dimensioni di una pipe con
fcntl(fd, F_SETPIPE_SZ, size) |
dove size è un long. La massima dimensione si trova in /proc/sys/fs/pipe-max-size.
Riferimenti
Popular Posts:
- None Found
[…] has published an excellent lesson about Linux pipes. Unix based operating systems like Linux offer a unique approach to join two commands on the […]
ps -ef |grep http|wc -l
is a useless use of wc, a better way would be:
ps -ef |grep -c http
which achieves the same thing with one less process call.
similarly, in
diff < (cd dir1 && find | sort) <(cd dir2 && find | sort)
“cd dir1 && find” can be rewritten “find dir1”.
(Note: to compare directory _contents_, you can use diff -R)
I highly recommend http://mywiki.wooledge.org/BashGuide/InputAndOutput#Pipes for more detailed info
Thanks for the link.
In the particular case you might replace
awk '{print $1}'
with
cut -f1
into
tar -cf - . | pv -s $(du -sb . | awk '{print $1}') | gzip > out.tgz
Thanks for the tip.
beautiful howto! thanks
Pol