Compter le nombre d'octets acheminés d'un processus à un autre

17

J'exécute un script shell qui canalise les données d'un processus à un autre

process_a | process_b

Quelqu'un connaît-il un moyen de savoir combien d'octets ont été passés entre les deux programmes? La seule solution à laquelle je peux penser pour le moment serait d'écrire un petit programme c qui lit depuis stdin, écrit dans stdout et compte toutes les données transférées, stockant le compte dans une variable d'environnement, comme:

process_a | count_bytes | process_b

Quelqu'un at-il une solution plus soignée?

Simon Hodgson
la source

Réponses:

16

Tuyau à travers dd. L'entrée par défaut de dd est stdin et la sortie par défaut est stdout; à la fin des E / S stdin / stdout, il rendra compte à stderr de la quantité de données transférées.

Si vous souhaitez capturer la sortie de dd et que les autres programmes parlent déjà à stderr, utilisez un autre descripteur de fichier. Par exemple,

$ exec 4>~/fred
$ input-command | dd 2>&4 | output-command
$ exec 4>&-
Phil P
la source
2
Ne pourriez-vous pas ignorer execle fichier et simplement l'exporter directement dans le fichier? input-command | dd 2>~/fred | output-command
pause jusqu'à nouvel ordre.
2
Euh, oui. Je vis apparemment un de "ces" moments, désolé.
Phil P
28

Utilisez pv le visualiseur de tuyaux. C'est un excellent outil. Une fois que vous en aurez connaissance, vous ne saurez jamais comment vous viviez sans.

Il peut également vous montrer une barre de progression et la «vitesse» du transfert.

Rory
la source
Dans ma recherche, j'étais tombé sur cela, mais j'en ai besoin pour définir une variable avec le nombre d'octets transférés afin de pouvoir l'utiliser dans un autre processus.
Simon Hodgson
Exemple d'utilisation: cat file | pv -bretournera la taille du fichier.
rodorgas
6

process_a | tee >(process_b) | wc --bytespourrait fonctionner. Vous pouvez ensuite rediriger wcle décompte vers l'endroit où vous en avez besoin. Si process_bquelque chose sort vers stdout/ stderrvous devrez probablement rediriger cela quelque part, ne serait-ce que /dev/null.

Pour un exemple légèrement artificiel:

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

À titre d'explication: teevous permet de diriger la sortie vers plusieurs fichiers (plus stdout) et la >()construction est la "substitution de processus" de bash qui fait ressembler un processus à un fichier en écriture seule dans ce cas afin que vous puissiez rediriger vers des processus ainsi que des fichiers ( voir ici , ou cette question + réponse pour un exemple d'utilisation teepour envoyer la sortie à de nombreux processus).

David Spillett
la source
J'aime cette solution, malheureusement le shelll que j'utilise (BusyBox) ne semble pas prendre en charge la notation> (), mais il fournit un moyen de faire ce que je recherche.
Simon Hodgson
Oui, vous avez besoin d'un bash assez complet pour avoir cette fonctionnalité - c'est le genre de chose qui n'est pas couramment utilisé, donc il est supprimé des coquilles coupées (même celles qui ont pour objectif d'être plus ou moins compatible avec bash) comme busybox afin d'économiser de l'espace.
David Spillett
1

Je sais que je suis en retard à la fête, mais je pense avoir une bonne réponse qui peut améliorer ce fil utile.
Il s'agit d'un mélange de @Phil P et @David Spillett réponse, mais:

  • différemment de @Phil P, il évite de créer un nouveau fichier
  • différemment de @David Spillett, il maintient la structure du pipeline

Le nombre d'octets est imprimé sur stdout, avec toute sortie de process_b.
Vous pouvez utiliser un préfixe pour identifier la ligne contenant des octets lorsque vous travaillez avec la sortie ( Bytes:dans l'exemple).

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

AVERTISSEMENT:
ne vous fiez pas à l'ordre des lignes dans la sortie
L'ordre est imprévisible et il peut toujours différer, même lors de l'appel du même script avec les mêmes paramètres!

Claudio
la source
Malheureusement, c'est toujours une construction bash seulement ...
Mikhail T.