Kann ich die Ausgabe einer Pipe duplizieren?


7

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 Hashes müssen für eine spätere Ausgabekomposition in MD- und SH-Variablen eingefügt werden.

Während die verarbeiteten Dateien wirklich groß sind (Hunderte von GB), versuche ich, Daten nach dem Lesen mehrfach zu verwenden. Ich habe etwas gefunden, das als Prozesssubstitution bezeichnet wird und das ich auf die nächste Weise übernommen habe:

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

anstatt:

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

Aber ich fand das nächste:

  • Es gibt anscheinend keine Ressource und keine Zeitersparnis, da beide ungefähr benötigen. 40s (für 4,776 GB Datei)

  • Ich habe keine Ahnung, wie das Ergebnis des Unterprozesses >(md5sum )in der Variablen MD gespeichert werden soll, um es später im Skript zu verwenden

Ich habe versucht, die Pipexec zu verstehen, aber selbst die schönen Farbabbildungen waren bis jetzt kein Erfolg.

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


Natürlich geht es nicht schneller, wenn anstelle von zwei Prozessen, die dieselben Daten frei abfressen, Sie 6 oder 7 gemacht haben und diese in kleinen Stücken zwischen ihnen austauschen ;-) Versuchen Sie dies set $(cut -d' ' -f1 <(md5sum $big) <(sha1sum $big)); md5sum=$1; sha1sum=$2.
Mosvy

Übrigens, Sie haben dort ein verrückt schnelles Rig, das in der Lage ist, eine ~ 5 TB-Datei in 40 Sekunden zu md5sum ;-)
mosvy

Entschuldigung, Mosvy, der Dezimalpunkt ist während der Bearbeitung aus der Zahl verschwunden. Natürlich sind 40 Sekunden für 4,776 GB; Wenn ich mit 5 GB stehen würde, könnte es korrekter sein.
schweik

nur für den Fall , dass nicht klar ist, geht der Prozess - Substitutionen (z. B. die a, b, cin cmd <(a) <(b) <(c)) werden immer parallel laufen, nicht sequentiell. Außerdem verwenden moderne Systeme (viel) Caching. Wenn also zwei völlig unterschiedliche Prozesse dieselbe Datei gleichzeitig lesen und sich ihre Geschwindigkeit nicht so stark unterscheidet, werden die Daten nur einmal aus dem Sicherungsspeicher abgerufen.
Mosvy

Antworten:


3

In Bezug auf die Leistung 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. Also auch wenn Sie so arbeiten. Für das, was es wert ist, haben Sie reduzierte Festplatten-E / A.

Das brauchen Sie wirklich nicht dd. Sie können die Ausgabe von sha1sum und md5sum auch einfach zur späteren Verwendung direkt in eine Datei schreiben

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 bei AFAIK nicht möglich ist, zwei Variablen gleichzeitig mit unterschiedlichen Werten festzulegen. Sie können eine direkt in eine Variable erfassen, aber nicht beide. Wenn Sie beide zulassen md5sumund gleichzeitig sha1sumauf dasselbe Standard schreiben, kann dies zu unvorhersehbaren Problemen führen.


Nun, das ddwurde verwendet, um anzuzeigen, dass ich die Daten von einem anderen Prozess erhalten kann (Schnitzen, Komprimieren); Wenn ich es verstehe, kann ich mich auf die Pufferung des Kernels verlassen, damit die Daten nicht zweimal gelesen werden.
schweik

2

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 es einfach ist, zwischen sha1 und md5 zu unterscheiden (unterschiedliche Länge, damit keine Verwirrung darüber besteht, welche welche ist).

Es gibt auch Dienstprogramme, die mehrere Prüfsummen selbst berechnen, ohne mit durch Reifen zu springen tee.

Eigentlich kann das obige auch geschrieben werden ohne tee:

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

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

In der Praxis sollte das parallele Ausführen beider Reader (& Hintergrund) es dem Festplatten-Cache ermöglichen, damit umzugehen, sodass Daten effektiv nur noch 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 über das zweimalige Lesen in einem anderen Kontext hier geschrieben: Verwenden von pv mit md5sum - obwohl es normalerweise funktioniert, gibt es einige Risiken, daher teeist es immer noch die zuverlässigere Methode.)


ein einziger waitwartet auf mehrere
aufgaben

Du hast recht, mein Test enthielt einen Tippfehler. Das tut mir leid. Fühlen Sie sich frei, die Bearbeitung zurückzusetzen.
Philip Couling

2

parsetvon GNU Parallel dient zum parallelen Setzen von Variablen und --teeleitet die Eingabe an mehrere Befehle weiter:

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

parset sumarr --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo ${sumarr[1]}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.