Cuenta el número de bytes canalizados de un proceso a otro


17

Estoy ejecutando un script de shell que canaliza datos de un proceso a otro

process_a | process_b

¿Alguien sabe una manera de averiguar cuántos bytes se pasaron entre los dos programas? La única solución que puedo pensar en este momento sería escribir un pequeño programa c que lea de stdin, escriba en stdout y cuente todos los datos transferidos, almacenando el conteo en una variable de entorno, como:

process_a | count_bytes | process_b

¿Alguien tiene una solución más ordenada?

Respuestas:


16

Tubería a través de dd. La entrada predeterminada de dd es stdin y la salida predeterminada es stdout; cuando termine la E / S stdin / stdout, informará a stderr sobre la cantidad de datos que transfirió.

Si desea capturar la salida de dd y los otros programas ya hablan con stderr, use otro descriptor de archivo. P.ej,

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

2
¿No podría omitir el execy simplemente enviarlo directamente al archivo? input-command | dd 2>~/fred | output-command
— Pausado hasta nuevo aviso.

2
Uh si. Aparentemente estaba teniendo uno de "esos" momentos, lo siento.
— Phil P

28

Utilice pv el visor de tuberías. Es una gran herramienta. Una vez que lo sepas, nunca sabrás cómo viviste sin él.

También puede mostrarle una barra de progreso y la 'velocidad' de la transferencia.


En mi búsqueda me encontré con esto, pero lo necesito para establecer una variable con el número de bytes transferidos para poder usarlo en otro proceso.
— Simon Hodgson

Ejemplo de uso: cat file | pv -bdevolverá el tamaño del archivo.
— rodorgas

6

process_a | tee >(process_b) | wc --bytesPodría funcionar. Luego puede redirigir wcel recuento a donde lo necesite. Si process_bgenera algo a stdout/ stderrprobablemente necesitará redirigir esto a alguna parte, aunque solo sea /dev/null.

Para un ejemplo ligeramente artificial:

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

A modo de explicación: le teepermite dirigir la salida a múltiples archivos (más stdout) y la >()construcción es la "sustitución de procesos" de bash, lo que hace que un proceso se vea como un archivo de solo escritura en este caso para que pueda redirigir a procesos y archivos ( vea aquí , o esta pregunta + respuesta para ver un ejemplo del uso teepara enviar resultados a muchos procesos).


Me gusta esta solución, lamentablemente el shelll que estoy usando (BusyBox) no parece admitir la notación> (), pero proporciona una forma de hacer lo que busco.
— Simon Hodgson

Sí, necesitas un bash bastante completo para tener esa característica: es el tipo de cosa que no se usa comúnmente, por lo que se elimina de los shells reducidos (incluso aquellos con el objetivo de ser más o menos compatibles con bash) como busybox para ahorrar espacio.
— David Spillett

1

Sé que llego tarde a la fiesta, pero creo que tengo una buena respuesta que puede mejorar este útil hilo.
Esta es una mezcla de @Phil P y @David Spillett, pero:

  • a diferencia de @Phil P 's, evita crear un nuevo archivo
  • a diferencia de @David Spillett, mantiene la estructura de la tubería

El conteo de bytes se imprime en stdout, junto con cualquier salida de process_b.
Puede usar un prefijo para identificar la línea que contiene bytes al trabajar con la salida ( Bytes:en el ejemplo).

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

ADVERTENCIA:
No confíe en el orden de las líneas en la salida. ¡
El orden es impredecible y siempre puede diferir, incluso cuando se llama al mismo script con los mismos parámetros!


Lamentablemente, sigue siendo una construcción de solo bash ...
— Mikhail T.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.