Zählen Sie die Anzahl der von einem Prozess zu einem anderen weitergeleiteten Bytes

17

Ich führe ein Shell-Skript aus, das Daten von einem Prozess zu einem anderen leitet

process_a | process_b

Kennt jemand einen Weg, um herauszufinden, wie viele Bytes zwischen den beiden Programmen übertragen wurden? Die einzige Lösung, die ich mir im Moment vorstellen kann, wäre, ein kleines c-Programm zu schreiben, das von stdin liest, in stdout schreibt und alle übertragenen Daten zählt, wobei die Anzahl in einer Umgebungsvariablen gespeichert wird, wie:

process_a | count_bytes | process_b

Hat jemand eine ordentlichere Lösung?

Simon Hodgson
quelle

Antworten:

16

Pipe through dd. Die Standardeingabe von dd ist stdin und die Standardausgabe ist stdout. Wenn stdin / stdout I / O beendet ist, wird stderr darüber informiert, wie viele Daten übertragen wurden.

Wenn Sie die Ausgabe von dd erfassen möchten und die anderen Programme bereits mit stderr sprechen, verwenden Sie einen anderen Dateideskriptor. Z.B,

$ exec 4>~/fred
$ input-command | dd 2>&4 | output-command
$ exec 4>&-
Phil P
quelle
2
Könnten Sie das nicht überspringen execund direkt in die Datei ausgeben? input-command | dd 2>~/fred | output-command
Bis auf weiteres angehalten.
2
Äh ja Ich hatte anscheinend einen dieser Momente, sorry.
Phil P
28

Verwendung pv das Rohr Betrachter. Es ist ein großartiges Werkzeug. Sobald Sie davon erfahren, werden Sie nie wissen, wie Sie ohne es gelebt haben.

Es kann auch einen Fortschrittsbalken und die Übertragungsgeschwindigkeit anzeigen.

Rory
quelle
Bei meiner Suche war ich auf dieses Problem gestoßen, aber ich muss eine Variable mit der Anzahl der übertragenen Bytes festlegen, damit ich es in einem anderen Prozess verwenden kann.
Simon Hodgson
Anwendungsbeispiel: cat file | pv -bGibt die Größe der Datei zurück.
Rodorgas
6

process_a | tee >(process_b) | wc --byteskönnte funktionieren. Sie können dann die wcZählung dahin umleiten , wo immer Sie sie benötigen. Wenn process_birgendetwas an stdout/ stderrausgegeben wird, müssen Sie dies wahrscheinlich irgendwo umleiten, wenn nur /dev/null.

Für ein leicht erfundenes Beispiel:

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

Zur Erklärung: teeErmöglicht die direkte Ausgabe in mehrere Dateien (plus stdout) und das >()Konstrukt ist die "Prozessersetzung" von bash, wodurch ein Prozess in diesem Fall wie eine Nur-Schreib-Datei aussieht, sodass Sie sowohl zu Prozessen als auch zu Dateien umleiten können ( siehe hier , oder diese Frage + Antwort für ein Beispiel der Verwendung von teeAusgabe zu vielen Prozesse zu senden).

David Spillett
quelle
Diese Lösung gefällt mir, leider scheint die von mir verwendete Shell (BusyBox) die> () -Notation nicht zu unterstützen, bietet aber eine Möglichkeit, das zu tun, wonach ich suche.
Simon Hodgson
Ja, Sie benötigen eine ziemlich vollständige Bash-Funktion, um diese Funktion nutzen zu können. Diese Funktion wird normalerweise nicht verwendet. Daher werden abgeschnittene Muscheln entfernt (auch solche mit dem Ziel, mehr oder weniger Bash-kompatibel zu sein). wie busybox um platz zu sparen.
David Spillett
1

Ich weiß, dass ich zu spät zur Party komme, aber ich glaube, ich habe eine gute Antwort, die diesen nützlichen Thread verbessern kann.
Dies ist eine Mischung aus @Phil P und @David Spillett, aber:

  • anders als bei @Phil P wird das Erstellen einer neuen Datei vermieden
  • anders als bei @David Spillett wird die Pipeline-Struktur beibehalten

Die Anzahl der Bytes wird zusammen mit der Ausgabe von process_b auf stdout ausgegeben.
Sie können ein Präfix verwenden, um die Zeile zu identifizieren, die Bytes enthält, wenn Sie mit der Ausgabe arbeiten ( Bytes:im Beispiel).

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

WARNUNG: Verlassen
Sie sich nicht auf die Reihenfolge der Zeilen in der Ausgabe.
Die Reihenfolge ist unvorhersehbar und kann immer unterschiedlich sein, auch wenn dasselbe Skript mit denselben Parametern aufgerufen wird!

Claudio
quelle
Leider ist es immer noch ein reines Bash-Konstrukt ...
Mikhail T.