tar-Archive ohne lokalen Speicher zwischen Servern streamen
Um ein Verzeichnis zwischen zwei Servern zu kopieren, leiten Sie auf der Quellseite den Befehl
tar durch SSH an den Befehl tar auf der Zielseite weiter.
Das Archiv durchläuft Ihren Computer, ohne als lokale Datei gespeichert zu werden. Das Ziel benötigt
Platz für die extrahierten Dateien, aber keiner der Server benötigt Platz für ein Zwischenarchiv.
Der Weg ist Quellserver → Ihr Computer → Zielserver. Ihr Computer überträgt den gesamten Datenstrom und muss verbunden bleiben; die Server benötigen keinen SSH-Zugriff aufeinander. Wenn die Bytes Ihren Computer vollständig umgehen müssen, führen Sie die Übertragung auf einem Host mit den nötigen Serververbindungen und Zugangsdaten aus.
SSH verschlüsselt die Kommunikation mit jedem Server. Das Archiv wird in der lokalen Pipe entschlüsselt und für das Ziel erneut verschlüsselt. Verwenden Sie daher einen vertrauenswürdigen Computer. Für die Transportverschlüsselung müssen Sie dieser Pipeline kein OpenSSL-Passwort hinzufügen.
Quelle und Ziel vorbereiten
Dieses Beispiel kopiert app-data aus dem Home-Verzeichnis des Quellkontos in ein
neues Verzeichnis app-data.incoming im Home-Verzeichnis des Zielkontos. Ersetzen Sie
source-server und destination-server durch Ihre SSH-Aliasse oder
Adressen im Format user@host. Passen Sie die Pfade in beiden Skripten an, wenn Ihre
Daten anderswo liegen.
Sie benötigen Bash auf dem Computer, der die Skripte ausführt, sowie OpenSSH-Zugriff auf zwei
Linux-Konten mit GNU tar, GNU find und GNU sha256sum. Das Quellkonto muss jede
Datei lesen können; das Zielkonto muss das Eingangsverzeichnis und dessen Inhalt erstellen können.
Richten Sie die schlüsselbasierte Authentifizierung ein, laden Sie alle verschlüsselten Schlüssel
in Ihren SSH-Agenten und prüfen Sie vor dem Start die Hostschlüssel beider Server. Die Befehle
verwenden BatchMode=yes. Daher schlagen sie fehl,
statt während einer Übertragung Passwörter oder eine Bestätigung der Hostschlüssel anzufordern.
Unterbinden Sie Schreibzugriffe auf das Quellverzeichnis, bis Kopieren und Prüfung abgeschlossen sind, oder lesen Sie aus einem konsistenten Snapshot. Bei einer Webanwendung umfasst dies auch Uploads und Hintergrundjobs. Verwenden Sie für Datenbankdaten das Sicherungsverfahren der Datenbank: Das Kopieren aktiver Datenbankdateien mit tar erzeugt keine konsistente Datenbanksicherung. Diese Befehle kopieren Dateien; die Einrichtung der Anwendung und die Umstellung des Datenverkehrs sind separate Schritte.
Die Beispiele wurden mit Bash 5.1.16, GNU tar 1.34 und OpenSSH 8.9p1 unter Linux getestet. Der Prüfsummenschritt verwendet GNU find und coreutils; dies ist keine Befehlsanleitung für macOS.
In ein neues Verzeichnis streamen
Speichern Sie dies als transfer.sh auf Ihrem Computer und führen Sie es mit
bash transfer.sh aus:
#!/usr/bin/env bash
set -euo pipefail
ssh -T -o BatchMode=yes source-server 'test -d app-data'
ssh -T -o BatchMode=yes destination-server 'mkdir app-data.incoming'
ssh -T -o BatchMode=yes source-server 'tar -cf - -C app-data .' |
ssh -T -o BatchMode=yes destination-server 'tar -xf - -C app-data.incoming'
printf 'Transfer completed; verify app-data.incoming before using it.\n'
Der einfache Befehl mkdir schlägt bewusst fehl, wenn das Eingangsverzeichnis
bereits existiert. Wählen Sie für einen erneuten Versuch einen neuen Pfad oder prüfen und entfernen
Sie zunächst das Verzeichnis einer fehlgeschlagenen Übertragung. So verhindert das Beispiel, dass
beim Extrahieren ein vorhandenes Anwendungsverzeichnis überschrieben wird.
Grundlagen des Streamings mit tar verstehen
In tar -cf - erstellt c ein Archiv und
f - sendet es an die Standardausgabe. In tar -xf -
extrahiert x das Archiv, das von der Standardeingabe gelesen wird.
Dies sind dieselben Vorgänge, die üblicherweise als tar cf - und
tar xf - geschrieben werden.
-C app-data ändert das Arbeitsverzeichnis von tar,
bevor es . archiviert. Archiveinträge, einschließlich versteckter
Dateien, erhalten daher Namen wie ./uploads/photo.jpg statt eines Verzeichnispräfixes,
das Sie später entfernen müssten. Beim Extrahieren legt -C diese
Einträge unter app-data.incoming ab. Das Verzeichnis wird dadurch nicht erstellt.
-T deaktiviert die Zuweisung eines Pseudoterminals durch SSH, damit die
Verbindung Binärdaten übertragen kann.
pipefail lässt die Pipeline fehlschlagen,
wenn einer der beiden SSH-Befehle fehlschlägt; set -e beendet dann das Skript
vor der Abschlussmeldung. Ohne pipefail kann der tar-Prozess auf der Quellseite
fehlschlagen, nachdem er ein extrahierbares Archiv erzeugt hat, während die Zielseite erfolgreich
endet. SSH gibt den Exit-Status des entfernten Befehls zurück,
sodass Bash diesen Fehler erkennen kann.
Ein erfolgreicher Durchlauf gibt die Abschlussmeldung aus und hinterlässt den kopierten
Verzeichnisbaum in app-data.incoming. Ein fehlgeschlagener Durchlauf kann dort
unvollständige Dateien hinterlassen. Weder ein Exit-Status von null noch die Abschlussmeldung
belegt, dass eine sich ändernde Quelle konsistent kopiert wurde.
Kopierte Dateien prüfen
Lassen Sie die Quelle unverändert und speichern Sie dies als verify.sh.
Führen Sie nach der Übertragung bash verify.sh aus:
#!/usr/bin/env bash
set -euo pipefail
ssh -T -o BatchMode=yes source-server \
'cd app-data && find . -type f -exec sha256sum -- {} +' |
ssh -T -o BatchMode=yes destination-server \
'cd app-data.incoming && sha256sum --check --strict -'
printf 'Regular-file checksums match.\n'
Dies streamt eine Prüfsummenliste zwischen den Servern, ebenfalls ohne sie lokal zu speichern.
GNU sha256sum --check gibt für jede übereinstimmende Datei
./filename: OK aus und schlägt bei fehlenden oder abweichenden Dateien fehl. GNU
find -exec … {} + meldet ebenfalls einen Fehler,
wenn ein Prüfsummenbefehl fehlschlägt. So wird auch die Quellseite dieser Pipeline geprüft.
Die abschließende Meldung ist nur zu erwarten, wenn beide Seiten erfolgreich sind.
Die Prüfung liest jede reguläre Datei auf beiden Servern erneut. Sie setzt mindestens eine reguläre Datei voraus und prüft Dateiinhalte, jedoch keine Ziele symbolischer Links, leeren Verzeichnisse, Berechtigungen, Eigentumsverhältnisse oder zusätzlichen Dateien am Ziel. Dies ist eine Anleitung zum Kopieren von Verzeichnissen, keine vollständige Systemsicherung: Die Erhaltung von ACLs oder erweiterten Attributen wird nicht angefordert. Prüfen Sie die Metadaten, die Ihre Anwendung benötigt, bevor Sie die Anwendung auf das kopierte Verzeichnis umstellen.
Übertragung bei Bedarf anpassen
Für eine Fortschrittsanzeige installieren Sie pv auf Ihrem Computer und
fügen Sie es in die Übertragungspipeline ein:
ssh … | pv | ssh …. Belassen Sie die Pipeline im Skript mit
pipefail. Das
Handbuch zu pv beschreibt die Byteanzahl,
die verstrichene Zeit und die Übertragungsrate. Ohne bekannte Gesamtgröße des Datenstroms kann das
Programm weder einen aussagekräftigen Fortschritt in Prozent noch eine voraussichtliche
Abschlusszeit angeben. Seine Ausgabe misst Bytes, die durch die lokale Pipe fließen, keine
geprüften Dateien.
Wenn der Zugriff einen Bastion-Host erfordert, ergänzen Sie jeden SSH-Befehl in beiden Skripten um
-J bastion-host. Richten Sie auch für diesen Host die Authentifizierung und die
Hostschlüsselprüfung ein.
ProxyJump verbindet sich über den Bastion-Host
mit dem Ziel; die Pipe zwischen den beiden SSH-Befehlen läuft weiterhin auf Ihrem Computer.
Identitäts- und Porteinstellungen für den Sprunghost gehören in Ihre SSH-Konfiguration, da
Befehlszeilenoptionen im Allgemeinen für das endgültige Ziel gelten.
Für komprimierbare Daten über eine Verbindung mit begrenzter Bandbreite ändern Sie
tar -cf - in tar -czf - und
tar -xf - in tar -xzf -. Dies verwendet die
Option --gzip von tar und erfordert gzip
auf beiden Servern. Es kostet CPU-Zeit und bringt bei bereits komprimierten Videos, Bildern oder
Archiven möglicherweise wenig. Messen Sie mit Ihren Dateien und Ihrer Verbindung, bevor Sie davon
ausgehen, dass die Übertragung dadurch schneller wird.
Häufige Probleme beheben
- Zugriff verweigert oder Datenträger voll: Lesen Sie stderr beider SSH-Befehle. Prüfen Sie die Lesbarkeit der Quelle, die Berechtigungen am Ziel, den freien Speicherplatz und die verfügbaren Inodes. Beheben Sie die Ursache und beginnen Sie mit einem neuen Eingangsverzeichnis; verwenden Sie keine unvollständige Kopie.
- „File changed as we read it“: Stoppen Sie den schreibenden Prozess oder verwenden Sie einen Snapshot. Wiederholen Sie anschließend die Übertragung und die Prüfsummenprüfung. Das Unterdrücken der Warnung kann eine Kopie laufend geänderter Daten nicht konsistent machen.
- Unerwartete Archivfehler: Startdateien der entfernten Shell dürfen bei nichtinteraktiven
Befehlen keine Begrüßungen auf stdout ausgeben. Diese Ausgabe würde in den Archivdatenstrom
gelangen. Geben Sie Diagnosen weiterhin auf stderr aus; leiten Sie stderr nicht mit
2>&1oder|&in die Pipe um. - Verbindungsabbruch: Dieser tar-Datenstrom lässt sich nicht fortsetzen.
tmuxoderscreenkönnen einen Prozess weiterlaufen lassen, wenn Sie sich von seinem Terminal lösen. Eine unterbrochene SSH-Verbindung in der Übertragungspipeline können sie jedoch nicht wiederherstellen. Starten Sie die Übertragung erneut in ein neues Verzeichnis und prüfen Sie es vor der Verwendung.
