Misura del transito in una pipeline Unix/Linux
by admin on May.01, 2009, under Hacking, Linux
Pipe Viewer o pv è un piccolo tool Unix/Linux scritto da Andrew Wood, in grado di misurare il transito di dati attraverso una pipeline.
Può essere infatti inserita in una qualsiasi normale pipeline tra due processi per ottenere una indicazione visiva della velocità con la quale i dati la attraversano, del tempo che ci impiegano per farlo, e di quanto tempo manchi al termine dell’attraversamento.
Va semplicemente inserito in una pipeline tra due processi, con le opzioni appropriate.
Il suo standard input viene semplicemente passato al suo standard output e lo stato del trasferimento viene visualizzato sullo standard error.
Un suggerimento per la comprensione di come operi sta nel paragonarla al comando cat, anche in termini prestazionali, come si può facilmente dedurre dagli esempi seguenti:
# ls -l lungo_log
-rw-r--r-- 1 adm adm 134272386 2009-04-23 00:42 lungo_log
# pv /var/log/lungo_log >/dev/null
128MB 0:00:00 [ 365MB/s] [========================================>] 100%
# time cat /var/log/lungo_log >/dev/null
real 0m0.366s
user 0m0.016s
sys 0m0.232s
# time pv /var/log/lungo_log >/dev/null
128MB 0:00:00 [ 378MB/s] [========================================>] 100%
real 0m0.362s
user 0m0.008s
sys 0m0.232s
# pv /var/log/lungo_log |gzip >/tmp/lungo_log_compresso
52.1MB 0:00:02 [37.3MB/s] [============> ] 40% ETA 0:00:02
Pipe viewer opera quindi come cat, con la differenza che viene visualizzata una “progress bar”. Si può anche vedere come gzip abbia processato 52.1MB di dati in 2 secondi. E’ stato processato il 40% dei dati e mancano altri 2 secondi al termine.
Si possono collegare differenti processi con differenti pv nel mezzo. Ad esempio, si può calcolare la velocità di lettura dei dati da disco e contemporaneamente quanti ne produca in output gzip:
# pv -cN lettura /var/log/lungo_log |gzip | pv -cN compressione >/tmp/lungo_log_compresso
compressione: 2.4MB 0:00:04 [ 552kB/s] [ <=> ]
lettura: 128MB 0:00:04 [28.8MB/s] [============================>] 100%
In questo caso è stato utilizzato il parametro “-N” per creare uno stream cui riferirsi tramite un nome. Il parametro -c è utile in associazione con -N (name) quando si utilizzano invocazioni multiple di pv all’interno di una singola pipeline, e assicura, usando sequenze di escape per il posizionamento del cursore, anziché usare carriage returns, l’ output non venga sporcato da un processo pv che scrive su un’altro.
L’esempio precedente mostra che il file “lungo_log” è stato letto ad una velocità di 28.8MB/s ma gzip ha scritto i dati a soli 552kB/s.
In tal modo è possibile calcolare immediatamente il rapporto di compressione ottenuto: 28.8 x 1024 / 552 = oltre 53x! come testimonia anche il rapporto tra la dimensione del file originale e dello stesso compresso (134272386 / 2514746 = 53.39).
La riga “compressione” non include la percentuale di dati trattati, dato che il processo pv successivo a gzip non ha alcuna idea di quanti dati gzip produrrà. Il primo processo pv, invece, lo sa.
Potremmo archiviare una intera directory di files in un tarball compresso:
$ tar -czf - . | pv > out.tgz
117MB 0:00:55 [2.7MB/s] [> ]
In tal modo pv mostra solamente la velocità dell’output del comando “tar -czf”. Non fornisce tuttavia alcuna informazione su quanti dati rimangano. A tal fine c’è bisogno di fornire a pv l’occupazione totale de dati che vogliamo archiviare con tar:
$ tar -cf - . | pv -s $(du -sb . | awk '{print $1}') | gzip > out.tgz
253MB 0:00:05 [46.7MB/s] [> ] 1% ETA 0:04:49
E’ stato “detto” a tar di creare (-c) un archivio di tutti i files presenti nella directory attuale (.) e produrre il proprio output in stdout (-f -). Poi viene specificata a pv la grandezza (-s) di tutti questi files. La tipica sostituzione Unix seguente ( $(du -sb . | awk ‘{print $1}’”) ) restituisce infatti tale valore come parametro “-s” a pv. Successivamente viene compresso l’intero contenuto della directory nel file out.tgz. In tal modo pv viene preventivamente a sapere siano ancora in attesa di essere processati e può determinare quanto tempo ancora (4 minuti e 49 secondi) occorre per terminare l’operazione.
Un semplice esempio che controlla quanto velocemente un file venga trasferito utilizzando nc:
# pv file | nc -w 1 host.pizzaefighi.com 3000
Si supponga che vi siano due computers, A e B, e che si voglia trasferire velocemente una directory da A a B.
Come si è gia visto, una possibilità consiste nell’ usare tar e nc, misurando il tempo dell’operazione con pv.
Su A, che ha un IP address 192.168.1.100:
# tar -cf - /path/to/dir | pv | nc -l -p 6666 -q 5
su B:
# nc 192.168.1.100 6666 | pv | tar -xf -
Tutti i files presenti in /path/to/dir sul computer A verranno trasferiti sul computer B, visualizzando quanto sia veloce l’operazione.
Se si vuole uno stato dell’avanzamento con progress bar, occorre utilizzare un espediente simile a quello usato in precedenza (pv -s $(…)) solo sul computer A.
Un altro esempio, puramente didattico, che mostra quannto velocemente si possa leggere da /dev/zero:
# pv /dev/zero > /dev/null
157GB 0:00:38 [4,17GB/s]

