Kann ich die Ausgabe einer Pipe duplizieren?

Kann ich die Ausgabe einer Pipe duplizieren?

Nun, die Aufgabe ist einfach: Ein Teil meines Skripts muss sowohl MD5- als auch SHA1-Hashes berechnen. Die Eingabe ist eine Datei – eine große Datei – und die Hashes müssen für die spätere Ausgabezusammenstellung in MD- und SH-Variablen eingefügt werden.

Da die verarbeiteten Dateien sehr groß sind (Hunderte von GB), versuche ich, die Daten nach dem Lesen mehrfach zu verwenden. Ich habe etwas namens Prozesssubstitution gefunden, das ich folgendermaßen übernommen habe:

$ dd if=big.tgz 2>/dev/null |tee >(sha1sum ) > >(md5sum ) ;

anstatt:

$ SH=$(sha1sum big.tgz); MD=$(md5sum big.tgz);

Aber ich habe das nächste gefunden:

  • es gibt offensichtlich weder Ressourcen noch Zeitersparnis, da beides ca. 40 Sekunden dauert (für eine 4,776 GB große Datei)

  • Ich habe keine Ahnung, wie ich das Ergebnis des Unterprozesses >(md5sum )in der Variable MD speichern kann, um es später im Skript zu verwenden

Ich habe versucht, Pipexec zu verstehen, aber selbst die schönen Farbabbildungen haben mir bisher keinen Erfolg gebracht.

Gibt es eine andere Möglichkeit als VAR=$(command), die Ausgabe in eine Variable umzuleiten?

Antwort1

Was die Leistung angeht, sind Sie möglicherweise durch die CPU eingeschränkt. Tatsächlich fühlen sich 4,7 TB in 40 Sekunden für MD5 und sha1sum schnell an. Selbst wenn Sie also so arbeiten, werden Sie weniger Festplatten-E/A benötigen.

Das ist wirklich nicht nötig dd. Sie können die Ausgabe von sha1sum und md5sum auch direkt in eine Datei schreiben, um sie später zu verwenden.

tee < big.tgz  >(sha1sum > big.tgz.sha1 ) > >(md5sum > big.tgz.md5 )
sha1=`cat big.tgz.sha1`
md5=`cat big.tgz.md5`

Ich schlage vor, temporäre Dateien wie diese ( big.tgz.sha1und big.tgz.md5) zu verwenden, da es meines Wissens nach nicht möglich ist, zwei Variablen gleichzeitig mit unterschiedlichen Werten festzulegen. Sie können eine direkt in einer Variablen erfassen, aber nicht beide. Und wenn Sie zulassen, dass sowohl als md5sumauch sha1sumgleichzeitig in dieselbe Standardausgabe geschrieben werden, kann dies zu unvorhersehbaren Problemen führen.

Antwort2

Nun, Sie können einfach eine weitere Weiterleitung hinzufügen:

tee < big.tgz >(sha1sum > big.tgz.sha1sum) >(md5sum > big.tgz.md5sum)

Sie können die Ausgabe auch so nehmen, wie sie ist, da zwischen SHA1 und MD5 leicht zu unterscheiden ist (unterschiedliche Länge, sodass es nicht zu Verwechslungen kommt).

Es gibt auch Dienstprogramme, die mehrere Prüfsummen selbstständig berechnen, ohne dass Sie sich mit durch Reifen springen müssen tee.

Eigentlich kann das Obige auch ohne geschrieben werden tee:

sha1sum big.tgz > big.tgz.sha1sum &
md5sum big.tgz > big.tgz.md5sum
wait # for sha1sum

Theoretisch ist dies schlecht, da die Daten zweimal von der Festplatte gelesen werden.

In der Praxis sollte der parallele (und im Hintergrund) Betrieb beider Lesegeräte es dem Festplattencache ermöglichen, damit umzugehen, sodass die Daten effektiv immer noch nur einmal gelesen werden. Dies setzt voraus, dass die Hash-Berechnung schnell und die E/A langsam ist, sodass kein Prozess vor dem anderen davonlaufen kann.

(Ich habe zuvor in einem anderen Zusammenhang hier etwas zum Thema zweimaliges Lesen gepostet:Verwenden von pv mit md5sum- obwohl es normalerweise funktioniert, ist es mit einigen Risiken verbunden und daher teeimmer noch die zuverlässigere Methode.)

Antwort3

parsetvon GNU Parallel dient zum parallelen Setzen von Variablen und --teeteilt die Eingabe mehreren Befehlen zu:

parset md5,sha1,sha256 --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo $sha1

parset sumarr --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo ${sumarr[1]}

verwandte Informationen