Contare il numero di byte inviati da un processo a un altro


17

Sto eseguendo uno script di shell che convoglia i dati da un processo a un altro

process_a | process_b

Qualcuno sa un modo per scoprire quanti byte sono stati passati tra i due programmi? L'unica soluzione a cui riesco a pensare al momento sarebbe quella di scrivere un piccolo programma c che legge da stdin, scrive su stdout e conta tutti i dati trasferiti, memorizzando il conteggio in una variabile d'ambiente, come:

process_a | count_bytes | process_b

Qualcuno ha una soluzione più ordinata?

Risposte:


16

Pipe through dd. l'input predefinito di dd è stdin e l'output predefinito è stdout; quando termina l'I / O stdin / stdout, riferirà a stderr su quanti dati ha trasferito.

Se vuoi catturare l'output di dd e gli altri programmi parlano già con stderr, usa un altro descrittore di file. Per esempio,

$ exec 4>~/fred
$ input-command | dd 2>&4 | output-command
$ exec 4>&-

2
Non potresti saltare l' execoutput direttamente al file? input-command | dd 2>~/fred | output-command
In pausa fino a nuovo avviso.

2
Si Apparentemente stavo vivendo uno di "quei" momenti, scusa.
Phil P,

28

Usa pv il visualizzatore di pipe. È un ottimo strumento. Una volta che lo conosci non saprai mai come hai vissuto senza di esso.

Può anche mostrarti una barra di avanzamento e la "velocità" di trasferimento.


Nella mia ricerca mi ero imbattuto in questo, ma ne ho bisogno per impostare una variabile con il numero di byte trasferiti in modo da poterlo utilizzare in un altro processo.
Simon Hodgson,

Esempio di utilizzo: cat file | pv -brestituirà la dimensione del file.
Rodorgas,

6

process_a | tee >(process_b) | wc --bytespotrebbe funzionare. Puoi quindi reindirizzare wcil conteggio verso dove mai ne hai bisogno. Se process_bemette qualcosa su stdout/ stderrprobabilmente dovrai reindirizzarlo da qualche parte, se non altro /dev/null.

Per un esempio leggermente inventato:

filestore:~# cat document.odt | tee >(dd of=/dev/null 2>/dev/null) | wc --bytes
4295

A titolo di spiegazione: tee consente di indirizzare l'output su più file (più stdout) e il >()costrutto è la "sostituzione di processo" di bash che rende un processo simile a un file di sola scrittura in questo caso in modo da poter reindirizzare a processi e file ( vedi qui o questa domanda + risposta per un esempio dell'uso teedi inviare output a molti processi).


Mi piace questa soluzione, purtroppo la shelll che sto usando (BusyBox) non sembra supportare la notazione> (), ma fornisce un modo per fare ciò che sto cercando.
Simon Hodgson,

Sì, hai bisogno di un bash abbastanza completo per avere quella caratteristica - è il genere di cose che non viene comunemente usato, quindi viene rimosso dalle shell tagliate (anche quelle con l'obiettivo di essere più o meno compatibili con bash) come busybox per risparmiare spazio.
David Spillett,

1

So di essere in ritardo alla festa, ma credo di avere una buona risposta che può migliorare questa discussione utile.
Questo è un mix di @Phil P e @David Spillett, ma:

  • diversamente da @Phil P, evita di creare un nuovo file
  • diversamente da @David Spillett, mantiene la struttura della pipeline

Il conteggio dei byte viene stampato su stdout, insieme a qualsiasi output di process_b.
È possibile utilizzare un prefisso per identificare la riga contenente byte quando si lavora con l'output ( Bytes:nell'esempio).

exec 3>&1
process_a | tee >({ echo -n 'Bytes:'; wc -c; } >&3) | process_b
exec 3>&-

ATTENZIONE:
non fare affidamento sull'ordine delle righe nell'output
L'ordine è imprevedibile e può sempre differire, anche quando si chiama lo stesso script con gli stessi parametri!


Purtroppo, è ancora un costrutto solo bash ...
Mikhail T.
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.