tar-Archive mit Zstd und LZ4 erstellen und vergleichen
Leiten Sie die Ausgabe von tar durch zstd oder lz4, um den Kompressor und seine Einstellungen explizit zu wählen.
Die folgende Anleitung erstellt beide Archive, stellt ihre Dateien wieder her und misst
Kompressionsdauer und Größe anhand derselben Eingabe. Jedes Archiv erhält erst nach erfolgreicher
Kompression einen neuen Namen; ein erneut ausgeführter Befehl kann kein vorhandenes Archiv ersetzen.
Werkzeuge prüfen
Verwenden Sie Linux mit Bash, GNU tar, GNU coreutils, diff, Python 3.9 oder neuer, Zstd und LZ4 1.10.0 oder neuer.
Die folgenden Befehle wurden mit GNU tar 1.35, Bash 5.3.15, Zstd 1.5.7, LZ4 1.10.0 und
Python 3.14.7 getestet. Installieren Sie fehlende Werkzeuge über den Paketmanager Ihrer Distribution
und prüfen Sie anschließend:
tar --version
bash --version
zstd --version
lz4 --version
python3 --version
ln --version
Die tar-Implementierung ist entscheidend.
GNU tar unterstützt --zstd,
bietet aber keine Option --lz4.
bsdtar unterstützt beim Erstellen von Archiven beide Optionen
und erkennt diese Formate beim Lesen. Diese Anleitung verwendet GNU tar und separate Kompressoren;
sie ist keine Shell-Anleitung für macOS/BSD, insbesondere weil ln -T
weiter unten eine GNU-Option ist.
Ein reproduzierbares Quellverzeichnis erstellen
Führen Sie jeden Bash-Block aus demselben Ausgangsverzeichnis aus. Die Klammern begrenzen die Wirkung
von cd und Shell-Optionen auf den jeweiligen Block.
Die Einrichtung verweigert die Wiederverwendung eines vorhandenen Verzeichnisses
tar-lab, sodass sie kein früheres Experiment überschreiben kann.
(
set -euo pipefail
mkdir tar-lab
cd -- tar-lab
mkdir project
python3 - <<'PY'
from pathlib import Path
import random
project = Path("project")
with (project / "records.csv").open("xb") as output:
for index in range(1_000_000):
output.write(f"{index:08d},user-{index % 1000:04d},GET,/assets/app.js,200\n".encode())
(project / "binary.bin").write_bytes(random.Random(0).randbytes(8 * 1024 * 1024))
(project / "empty.txt").touch()
(project / "omit.log").write_text("Exclude this log.\n", encoding="utf-8")
PY
)
Diese Fixtures kombinieren strukturierten Text mit deterministischen Pseudozufallsbytes und einer leeren Datei. Ändern Sie die Quelle während der Archivierung nicht. Ein erfolgreicher tar-Befehl liefert keinen konsistenten Schnappschuss von Dateien, die eine Anwendung gerade verändert.
Archive erstellen, ohne frühere Ausgaben zu ersetzen
Beide Beispiele archivieren project/ und lassen Namen aus, die dem Muster
*.log entsprechen, einschließlich verschachtelter Protokolldateien.
Das Muster in Anführungszeichen erreicht tar ohne Shell-Expansion. Bei tar erstellt
-c das Archiv; -f - sendet es an die
Standardausgabe. Der Kompressor schreibt in ein neues temporäres Verzeichnis neben dem endgültigen
Archiv, außerhalb des Quellverzeichnisbaums.
pipefail lässt bei einem Fehler im erzeugenden tar-Prozess die gesamte Pipeline
fehlschlagen, selbst wenn der Kompressor erfolgreich ist.
Es schützt keine Datei, die durch Shell-Umleitung geöffnet wurde: >
kann ein altes Backup leeren, bevor tar ausgeführt wird. Hier wird nur die temporäre Ausgabe
umgeleitet. Nachdem der Integritätstest des Kompressors bestanden wurde, gibt
GNU ln -T den vollständig geschriebenen
Bytes ihren endgültigen Namen. Ohne -f verweigert der Befehl dies, wenn
dort bereits eine Datei, ein Verzeichnis oder ein Symlink existiert.
Der temporäre und der endgültige Name liegen auf demselben Dateisystem, wie es Hardlinks erfordern.
Der Exit-Trap entfernt das temporäre Verzeichnis bei regulärem Erfolg oder Fehlschlag.
Das Zstd-Archiv erstellen
Verwenden Sie Stufe drei und einen Kompressions-Worker. Laut
Zstd-CLI-Handbuch bedeutet -T1 einen
Kompressions-Worker neben der Ein-/Ausgabe; dies unterscheidet sich von --single-thread.
(
set -euo pipefail
cd -- tar-lab
stage=$(mktemp -d .zstd.XXXXXX)
trap 'rm -rf -- "$stage"' EXIT
tar --exclude='*.log' -cf - project | zstd -3 -T1 -c > "$stage/archive"
zstd -t "$stage/archive"
ln -T -- "$stage/archive" project.tar.zst
printf 'Created project.tar.zst\n'
)
Das LZ4-Archiv erstellen
Verwenden Sie auch hier einen Kompressions-Worker, jedoch Stufe eins. LZ4 1.10.0 führte
Multithread-Kompression ein; das CLI-Handbuch dokumentiert
-T1. Ältere LZ4-Versionen unterstützen diese Option nicht.
(
set -euo pipefail
cd -- tar-lab
stage=$(mktemp -d .lz4.XXXXXX)
trap 'rm -rf -- "$stage"' EXIT
tar --exclude='*.log' -cf - project | lz4 -1 -T1 -c > "$stage/archive"
lz4 -t "$stage/archive"
ln -T -- "$stage/archive" project.tar.lz4
printf 'Created project.tar.lz4\n'
)
Bei Erfolg erscheint abschließend die entsprechende Meldung Created.
Eine erneute Ausführung liefert einen Status ungleich null und lässt die Bytes des vorhandenen
Archivs unverändert, selbst wenn project/ nicht mehr vorhanden ist.
Um ein weiteres Archiv zu erstellen, wählen Sie einen anderen endgültigen Dateinamen; entfernen
Sie kein früheres Backup, nur damit eine erneute Ausführung erfolgreich ist.
Ein erzwungenes Beenden oder ein Stromausfall kann temporäre Dateien zurücklassen. Diese Befehle
garantieren keine Datenbeständigkeit bei einem Absturz.
Dateien wiederherstellen und vergleichen
Ein Integritätstest prüft den komprimierten Stream, stellt aber nicht sicher, dass er die Dateien enthält, die Sie sichern wollten. Stellen Sie die Dateien in einem neuen Verzeichnis wieder her und vergleichen Sie es mit der unveränderten Quelle:
(
set -euo pipefail
cd -- tar-lab
zstd -t project.tar.zst
mkdir restored-zstd
zstd -dc project.tar.zst | tar -xf - -C restored-zstd
diff -r --exclude='*.log' project restored-zstd/project
printf 'Zstd restore matches the source.\n'
)
(
set -euo pipefail
cd -- tar-lab
lz4 -t project.tar.lz4
mkdir restored-lz4
lz4 -dc project.tar.lz4 | tar -xf - -C restored-lz4
diff -r --exclude='*.log' project restored-lz4/project
printf 'LZ4 restore matches the source.\n'
)
Erwartet werden keine Ausgabe von diff und die passende Erfolgsmeldung.
Die wiederhergestellten Verzeichnisbäume enthalten records.csv,
binary.bin und empty.txt; omit.log fehlt.
Verglichen werden Namen und Dateiinhalte, nicht Eigentümer, Berechtigungen oder sämtliche
Dateisystem-Metadaten. Eine erneute Wiederherstellung verweigert die Nutzung des bereits vorhandenen
Wiederherstellungsverzeichnisses. Ein Fehler beim Entpacken kann einen unvollständigen neuen
Verzeichnisbaum hinterlassen. Betrachten Sie die Wiederherstellung daher erst als erfolgreich,
wenn der Vergleich bestanden wurde. Verwenden Sie diese Befehle für Archive, die Sie selbst erstellt
haben und denen Sie vertrauen.
Den Kompromiss am selben tar-Stream messen
Führen Sie diesen Block nach der Einrichtung aus dem Ausgangsverzeichnis aus. Er erstellt ein temporäres, unkomprimiertes tar-Archiv mit fester Eintragsreihenfolge, festen Zeitstempeln und Eigentümern und misst anschließend jeden Kompressor und Decoder. Pro Codec gibt es einen Aufwärmlauf und fünf Messläufe. Jedes decodierte tar-Archiv muss bytegenau der Eingabe entsprechen. Nur die eigenen temporären Dateien des Benchmarks werden wiederverwendet; Ihre Archive und Wiederherstellungen bleiben unberührt.
python3 - <<'PY'
import hashlib
from pathlib import Path
from statistics import median
import subprocess
from tempfile import TemporaryDirectory
from time import perf_counter
def digest(path):
return hashlib.sha256(path.read_bytes()).digest()
def timed(command, source, destination):
with source.open("rb") as stdin, destination.open("wb") as stdout:
started = perf_counter()
subprocess.run(command, stdin=stdin, stdout=stdout, check=True)
return perf_counter() - started
with TemporaryDirectory(prefix="benchmark-", dir="tar-lab") as temporary:
work = Path(temporary)
raw = work / "input.tar"
with raw.open("xb") as output:
subprocess.run([
"tar", "--sort=name", "--mtime=@0", "--owner=0", "--group=0",
"--numeric-owner", "--exclude=*.log", "-cf", "-", "project",
], cwd="tar-lab", stdout=output, check=True)
expected = digest(raw)
raw_size = raw.stat().st_size
print(f"tar bytes: {raw_size}")
print("codec bytes compressed/tar compress_s decompress_s")
for codec, options in [("zstd", ["-3", "-T1"]), ("lz4", ["-1", "-T1"])]:
packed, decoded = work / codec, work / "decoded.tar"
samples = []
for run in range(6):
compress = timed([codec, *options, "-q", "-c"], raw, packed)
decompress = timed([codec, "-q", "-dc"], packed, decoded)
if digest(decoded) != expected:
raise RuntimeError(f"{codec} changed the tar bytes")
if run > 0:
samples.append((compress, decompress))
size = packed.stat().st_size
print(f"{codec} {size} {size / raw_size:.3f} "
f"{median(c for c, d in samples):.4f} {median(d for c, d in samples):.4f}")
PY
Die Zeitmessungen umfassen den Start der Unterprozesse und die lokale Datei-Ein-/Ausgabe, schließen aber die tar-Erstellung, das Entpacken der Einträge und den SHA-256-Vergleich aus. Es sind Messungen mit aufgewärmtem Cache, kein Test des Datenträgerdurchsatzes. Das Verhältnis ergibt sich aus komprimierten Bytes geteilt durch die Bytes des unkomprimierten tar-Archivs; kleiner ist besser.
Am 24. September 2026 ergaben die Fixtures unter Linux x86-64 mit einer AMD Ryzen AI Max+ 395 CPU ein tar-Archiv mit 50.401.280 Bytes. Mit den oben aufgeführten Werkzeugversionen lagen die Mediane der Laufzeiten bei:
| Kompressor und Optionen | Archivbytes | Komprimiert/tar | Komprimieren | Dekomprimieren |
|---|---|---|---|---|
Zstd -3 -T1 | 8.946.393 | 0,178 | 0,0281 s | 0,0124 s |
LZ4 -1 -T1 | 15.830.951 | 0,314 | 0,0519 s | 0,0332 s |
Zstd erzeugte in diesem Lauf das kleinere Archiv und schloss beide Vorgänge schneller ab. Die wiederholte CSV-Struktur und die Messwerte eines einzelnen Rechners begründen keine allgemeine Rangfolge. Ersetzen Sie die Fixtures durch repräsentative Dateien, bevor Sie einen Kompressor für Ihre Arbeitslast wählen, und prüfen Sie, ob der Empfänger das Format decodieren kann. Kurze Läufe reagieren empfindlich auf andere Aktivitäten auf dem Rechner.
Das Ergebnis in einem Backup-Workflow nutzen
Trennen Sie Kompression, Dateiauswahl und Backup-Verlauf. Die Auswahl kürzlich geänderter Dateien
mit find erfasst keine Löschungen. Für eine wiederherstellbare
Änderungskette folgen Sie der
Anleitung für inkrementelle Backups mit GNU tar.
Planen Sie ein Backup erst ein, nachdem Sie dessen Fehler- und Wiederherstellungsabläufe getestet
haben. Bewahren Sie frühere erfolgreiche Archive auf, bis Ihre Aufbewahrungsrichtlinie deren
Entfernung erlaubt.
Kopieren Sie für SSH-Übertragungen ein fertig erstelltes Archiv und überprüfen Sie es am Zielort. Wenn Sie ein Archiv in Teile aufteilen, behalten Sie deren exakte Reihenfolge für das Zusammensetzen bei und überprüfen Sie die zusammengesetzte Datei vor der Wiederherstellung. Weder die Übertragung noch das Aufteilen ändert die hier anhand der Messungen getroffene Kompressorwahl.
