Ich habe einen peinlich parallelen Prozess, der eine große Menge nahezu (aber nicht vollständig) identischer Dateien erstellt. Gibt es eine Möglichkeit, die Dateien "on the fly" zu archivieren, damit die Daten nicht mehr Speicherplatz als nötig beanspruchen?
Der Prozess selbst akzeptiert Befehlszeilenparameter und druckt den Namen jeder in stdout erstellten Datei. Ich rufe es auf, mit parallel --gnu
dem die Eingabe (die aus einem anderen Prozess stammt) verteilt und die Ausgabe gesammelt wird:
arg_generating_process | parallel --gnu my_process | magic_otf_compressor
EINFACHES BEISPIEL für den ersten Teil des Rohrs in bash
:
for ((f = 0; $f < 100000; f++)); do touch $f; echo $f; done
Wie könnte das magic_otf_compressor
aussehen? Es soll jede Eingabezeile als Dateinamen behandeln, jede Datei in ein komprimiertes .tar
Archiv kopieren (dasselbe Archiv für alle verarbeiteten Dateien!) Und es dann löschen. (Eigentlich sollte es ausreichen, den Namen jeder verarbeiteten Datei zu drucken, ein anderer | parallel --gnu rm
könnte sich um das Löschen der Dateien kümmern.)
Gibt es ein solches Werkzeug? Ich denke nicht daran, jede Datei einzeln zu komprimieren, dies würde viel zu viel Speicherplatz verschwenden. Ich habe nachgesehen archivemount
(wird das Dateisystem im Speicher halten -> unmöglich, meine Dateien sind zu groß und zu viele) und avfs
(konnte es nicht dazu bringen, mit FUSE zusammenzuarbeiten). Was habe ich vermisst?
Ich bin nur einen Schritt davon entfernt, ein solches Tool selbst zu hacken, aber jemand muss es schon einmal getan haben ...
EDIT : Im Wesentlichen denke ich, dass ich nach einem Standard-Front-End suche libtar
(im Gegensatz zum Befehlszeilen-Front-End tar
, das Argumente aus der Befehlszeile liest).
quelle
Antworten:
Es scheint
tar
, dass es alle Dateinamen im Voraus wissen möchte. Es ist also weniger on-the-fly und mehr after-the-fly.cpio
scheint dieses Problem nicht zu haben:quelle
tar
den Code geschaut, um festzustellen , dass es eine Funktion gibt, die den nächsten zu verarbeitenden Dateinamen zurückgibt, wodurch ich die Dokumentation erneut gelesen habe. - Wirdstdout
also über diegzip
Prozesssubstitution zum Prozess geleitet undstderr
umgeleitet, zustdout
welchem Prozess der nächste Schritt in der Pipe führt?tar
anhand des einfachen Beispiels, das ich meiner Frage hinzugefügt habe, bestätigen, dass zuerst die Dateiliste gelesen wird. Beim erneuten Lesentar
des Quellcodes scheint es mir jedoch, dass die Liste der Dateien "on the fly" gelesen werden sollte, wenn kein inkrementelles Archiv erstellt wird. Leider habe ich Fehler beim Kompilierentar
aus der Quelle ... :-(cpio
andere Möglichkeit gefunden, die letzte Zeile in der Ausgabe von zu unterdrücken alsgrep -v 'blocks$'
. (head -n -1
verwendet einen sehr großen Puffer ...) Macht diese Lösung ein bisschen zu einem Hack, aberhead -n -1
nur 16 MB, wenn es mit ein paar GB Daten ausgeführt wird. Sie können immer perl verwenden: perl -ne 'print $ last; $ last = $ _'Ein klassischer Fall von RTFM (alles!) . Die
-T
Option für GNUtar
liest die zu archivierenden Dateien aus einer anderen Datei (in meinem Fall/dev/stdin
können Sie sie auch verwenden-
), und es gibt sogar eine--remove-files
Option:(Verwenden Sie die parallele Version von
xz
für die Komprimierung, aber Sie können stattdessen Ihren bevorzugten Kompressor verwenden). Zu verwenden als:EDIT : Wie Ole betont,
tar
scheint-T
aus irgendeinem Grund die gesamte Liste der Dateien mit der Option zu lesen . Der folgende Test bestätigt dies:Auf meinem System gibt es eine Verzögerung von einer Sekunde, bevor alle Dateien gleichzeitig gedruckt werden. Wenn der
tar
Befehl dagegen durch ersetzt wirdcat
, werden alle Dateien beim Erstellen gedruckt. Ich habe eine Supportanfrage bei den Teerleuten gestellt, mal sehen.EDIT ^ 2 : Das neueste
tar
aus der Quelle behebt dies. Es ist noch nicht in Ubuntu 13.10 enthalten, könnte aber in 14.04 enthalten sein.quelle
Irgendwie scheint dies für einen soliden Kompressor (bandbasierte Archivierer + Komprimierung) kein guter Job zu sein. Das Einfügen von Dateien nacheinander sieht aus wie ein Job für
zip
oder ein anderes Format, das den zufälligen Dateizugriff innerhalb des Archivs und das inkrementelle Einfügen ermöglicht.Die Tatsache, dass die Dateien ähnlich sind, hilft in beiden Fällen nicht viel. In
zip
werden Dateien separat komprimiert, und in festen Kompressoren gibt es normalerweise ein Fenster, in dem die Komprimierung stattfindet.Wenn die Dateien textbasiert sind, können Sie Unterschiede im Vergleich zu einer einzelnen Referenzdatei speichern. Für Binärdateien ist es etwas kniffliger, kann aber durchgeführt werden.
Es gibt auch einen formalen Weg (nicht nur Schreiben, sondern richtige Dateisysteme). Beispielsweise bieten ZFS- und BTRFS-Dateisysteme eine transparente Komprimierung. Sie können auch diese http://developer.berlios.de/projects/fusecompress verwenden
quelle
xz
scheint mit einer Standardwörterbuchgröße von 8 MB (bei Standardkomprimierungsstufe-6
) zu arbeiten, was für meinen Anwendungsfall ausreichend zu sein scheint. - Diffs zu einer Referenzdatei sind nett, müssen aber zuerst eine Referenzdatei erstellen. Würde ein komprimierendes Dateisystem Dateien mit nahezu identischem Inhalt erkennen?btrfs
verfügt jedoch über Copy-on-Write. Wenn Sie also eine Datei kopieren und einen Teil davon ändern, werden nur Teile gespeichert, die Sie geändert haben. Wenn Sie Dateien nicht auf diese Weise erstellen, gibt es angeblich Deduplizierungswerkzeuge , aber esbtrfs
handelt sich noch nicht um ein ausgereiftes und stabiles Dateisystem. Die Deduplizierung befindet sich in einem frühen Entwicklungsstadium. Aber jetzt denke ich darüber nach, was ist mit lessfs.com/wordpressEs mag nicht offensichtlich erscheinen, aber ich wette, es
squashfs
wäre perfekt dafür - und es ist sogar im Kernel implementiert. Seit der Version 4.1squashfs
verarbeiten kann Pseudo-Dateien wie auf dem angegebenemksquash
Befehlszeile oder über einen Shell-Skript undmksquashfs
die Dateien erzeugt , wie es das Archiv erstellt.Es kann Rohre verarbeiten - zum Beispiel können Sie einen anderen Prozess
stdout
in einem montierbaren Squash-Archiv erfassen - sogar Fifos - es ist ziemlich cool. In Ihrem Fall, wenn Sie das Skript Logistik erarbeiten könnte Ihr Prozess der Ausgabe durch von Rohrleitungen, könnten Sie Ihren Prozess wickeln ganz inmksquashfs
und mit einem einzigen Archiv aufzuwickeln. Hier ist ein bisschen von derreadme
Funktionsweise und hier gibt es noch mehr :quelle
test
und einer Dateifile
in diesem Verzeichnis erstellt werden kann. Könnten Sie bitte ein kurzes Beispiel geben?