Ich habe 200 GB freien Speicherplatz, 16 GB RAM (von denen ~ 1 GB durch den Desktop und den Kernel belegt ist) und 6 GB Swap.
Ich habe eine 240 GB externe SSD, von der 70 GB 1 verwendet werden und der Rest frei ist, den ich auf meiner Festplatte sichern muss.
Normalerweise würde ich zuerst dd if=/dev/sdb of=Desktop/disk.img
die Festplatte komprimieren, aber das Erstellen des Images ist keine Option, da dies viel mehr Speicherplatz erfordern würde, als ich habe, obwohl der Komprimierungsschritt dazu führt, dass der freie Speicherplatz zusammengedrückt wird Das endgültige Archiv kann problemlos auf meine Festplatte passen.
dd
Schreibt standardmäßig in STDOUT und gzip
kann aus STDIN lesen. Theoretisch kann ich also schreiben dd if=/dev/sdb | gzip -9 -
, aber gzip
das Lesen von Bytes dauert erheblich länger als dd
das Produzieren.
Von man pipe
:
An das Schreibende der Pipe geschriebene Daten werden vom Kernel gepuffert, bis sie vom Leseende der Pipe gelesen werden.
Ich stelle mir eine |
wie eine echte Pipe vor - eine Anwendung schiebt Daten ein und die andere entfernt Daten so schnell wie möglich aus der Warteschlange der Pipe.
Was passiert, wenn das Programm auf der linken Seite mehr Daten schneller schreibt, als die andere Seite der Pipe darauf hoffen kann, sie zu verarbeiten? Wird es zu extremer Speicher- oder Auslagerungsauslastung führen oder wird der Kernel versuchen, ein FIFO auf der Festplatte zu erstellen, wodurch die Festplatte voll wird? Oder scheitert es einfach daran, SIGPIPE Broken pipe
wenn der Puffer zu groß ist?
Im Grunde läuft dies auf zwei Fragen hinaus:
- Was sind die Auswirkungen und Ergebnisse, wenn mehr Daten in eine Pipe verschoben werden, als gleichzeitig gelesen werden?
- Wie kann ein Datenstrom zuverlässig auf die Festplatte komprimiert werden, ohne dass der gesamte unkomprimierte Datenstrom auf der Festplatte gespeichert wird?
Hinweis 1: Ich kann nicht genau die ersten 70 verwendeten GB kopieren und erwarte, dass ich ein funktionierendes System oder Dateisystem erhalte, da die Fragmentierung und andere Dinge den vollständigen Inhalt erfordern.
quelle
lzop
anstattgzip
; es komprimiert viel schneller mit nur einem geringfügig niedrigeren Kompressionsverhältnis. Ich finde es ideal für Disk-Images, bei denen die Komprimierungsgeschwindigkeit ein echter Engpass sein kann.Antworten:
Technisch brauchen Sie nicht einmal
dd
:Wenn Sie tun
dd
, sollten Sie immer wie mit größer als Standard - Blockgröße gehendd bs=1M
oder die syscall Hölle leiden (dd
‚s Standard - Blockgröße beträgt 512 Byte, da esread()
s undwrite()
s das ist4096
syscalls proMiB
, zu viel Overhead).gzip -9
verwendet viel mehr CPU mit sehr wenig zu zeigen. Wenngzip
Sie langsamer werden, verringern Sie die Komprimierungsstufe oder verwenden Sie eine andere (schnellere) Komprimierungsmethode.Wenn Sie dateibasierte Sicherungen anstelle von
dd
Images ausführen , können Sie eine Logik verwenden, die entscheidet, ob die Komprimierung überhaupt durchgeführt werden soll oder nicht (dies ist für verschiedene Dateitypen nicht sinnvoll).dar
(tar
alternative`) ist ein Beispiel, das Möglichkeiten dazu hat.Wenn Ihr freier Speicherplatz NULL ist (da es sich um eine SSD handelt, die nach TRIM zuverlässig null zurückgibt und Sie
fstrim
Caches ausgeführt und gelöscht haben), können Siedd
mitconv=sparse
flag auch ein unkomprimiertes, schleifenmontierbares, spärliches Image erstellen, das keinen Speicherplatz für die Nullbereiche verwendet . Erfordert, dass die Image-Datei von einem Dateisystem gesichert wird, das Dateien mit geringer Dichte unterstützt.Alternativ gibt es für einige Dateisysteme Programme, die nur die verwendeten Bereiche abbilden können.
quelle
dd bs=1M
" - Sie können, aber erwarten Sie nicht zu viel. Auf meinem PCdd
werden mit 512-Byte-Blöcken ca. 2GB / s gemacht. Das wird nicht der Engpass sein;gzip
wird sein.dd
2 GB / s mit 512-Byte-Blöcken haben, wäre ich überrascht, wenn dabei nicht ein CPU-Kern zu 100% ausgeschöpft würde. Wenn es sich bei Ihrer Box um einen Quadcore handelt, der ohnehin nur im Leerlauf sitzt, werden Sie möglicherweise keinen Unterschied bemerken. Alle anderen tun es trotzdem.dd
wenn die Blockgröße erwähnt wird, kommen die Leute, um zu picken.gzip
CPU-intensiv zu sein war auch ein Teil meiner Antwort, okay? Und sorry, ich bin nicht einverstanden mit "vernachlässigbar". Es addiert sich vielleicht nur 1-2s pro Gig mitgzip -9
(aber das sind immer noch Minuten, wenn Hunderte von Gigs bearbeitet werden), aber wenn Sie Ihren Rat befolgen, istlzop -1
es 1s pro Gig vs. 4s pro Gig. Getestet auf einer Kartoffel (Single Core Vserver). Das Hinzufügen einer vernünftigen Blockgrößedd
kostet nichts und hat keine Nachteile. Nicht picken. Mach es einfach. ymmvdd
Liest und schreibt Daten blockweise und es steht immer nur ein Block aus. Sozeigt, dass
dd
etwa 1 MB Speicher verwendet. Sie können mit der Blockgröße herumspielen und sie fallen lassenvalgrind
, um den Effekt aufdd
die Geschwindigkeit zu sehen.Wenn Sie in die Pipe einsteigen
gzip
, werden Siedd
einfach langsamer, umgzip
der Geschwindigkeit zu entsprechen. Die Speichernutzung nimmt nicht zu und der Kernel speichert die Puffer auch nicht auf der Festplatte (der Kernel weiß nicht, wie das geht, außer über Swap). Ein Rohrbruch tritt nur auf, wenn eines der Rohrenden stirbt. siehesignal(7)
undwrite(2)
für Details.Somit
ist eine sichere Möglichkeit, das zu tun, wonach Sie suchen.
Beim Piping wird der Schreibvorgang vom Kernel blockiert, wenn der Lesevorgang nicht mithält. Sie können dies durch Laufen sehen
Sie werden sehen, dass 1
dd
MB angezeigt wird, und dann ein,write()
das dort sitzt und eine Minute wartet, während es ausgeführt wirdsleep
. So gleichen sich beide Seiten einer Pipe aus: Der Kernel blockiert das Schreiben, wenn der Schreibvorgang zu schnell ist, und blockiert das Lesen, wenn der Lesevorgang zu schnell ist.quelle
dd
man langsamer werden, um mitgzip
der Geschwindigkeit mitzuhalten? Es ist automatisch, wie vom Kernel, oder berechnet es aus Metadaten über seinen Ausgabedateideskriptor?dd
Aufrufewrite()
zum Einfügen von Daten in die Pipe.write()
überträgt die Kontrolle tatsächlich an den Kernel, damit dieser den Pipe-Speicher manipulieren kann. Wenn der Kernel erkennt, dass die Pipe voll ist, wartet er ("block"), bis die Pipe genug Platz hat. Erst dann wird derwrite()
Anruf beendet und die Steuerung an zurückgegebendd
, wodurch die Daten erneut in die Pipe geschrieben werden.Es gibt keine anderen negativen Auswirkungen als die Leistung: Die Pipe verfügt über einen Puffer, der normalerweise 64 KB groß ist. Danach wird ein Schreibvorgang in die Pipe einfach blockiert, bis
gzip
weitere Daten gelesen wurden.quelle
Beantwortung der eigentlichen Frage, wie es funktioniert: "Was passiert, wenn das Programm auf der linken Seite mehr Daten schneller schreibt, als die andere Seite der Pipe darauf hoffen kann, sie zu verarbeiten?"
Das passiert nicht. In der Pipe befindet sich ein relativ kleiner Puffer mit begrenzter Größe. siehe Wie groß ist der Pipe Buffer?
Sobald der Pipe-Puffer voll ist, blockiert das Sendeprogramm . Bei einem Schreibaufruf gibt der Kernel die Steuerung erst an das Programm zurück, wenn die Daten in den Puffer geschrieben wurden. Dies gibt dem Leseprogramm CPU-Zeit, um den Puffer zu leeren.
quelle
Vielleicht brauchst du nur die Dateien, dann benutze tar. Sie können die Blöcke mit Nullen füllen, die nichts enthalten, was Sie möchten, und jemand hat bereits danach gefragt. Löschen Sie nicht verwendeten Speicherplatz mit Nullen (ext3, ext4)
Dann gibt es
pigz
die meist schneller alsgzip
.quelle