Wie kann ich am besten eine große Anzahl kleiner Dateien über scp kopieren?

59

Ich habe ein Verzeichnis, das mehrere Gigabyte und mehrere tausend kleine Dateien hat. Ich möchte es mit scp mehr als einmal über das Netzwerk kopieren. Die CPU-Zeit auf den Quell- und Zielcomputern ist günstig, aber der Netzwerkaufwand, der durch das Kopieren jeder einzelnen Datei entsteht, ist enorm. Ich würde es tar / gzip und versenden, aber der Quellcomputer ist knapp auf der Festplatte.

Gibt es eine Möglichkeit für mich, die Ausgabe von tar -czf <output> <directory>zu scp zu leiten? Wenn nicht, gibt es eine andere einfache Lösung? Mein Quellcomputer ist uralt (SunOS), daher möchte ich lieber keine Dinge darauf installieren.

nmichaels
quelle

Antworten:

104

Sie können tar über eine SSH-Sitzung leiten:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"
pdo
quelle
3
+1 Teerrohrlösung. Wenn Sie mehr Bandbreite und weniger CPU haben, können Sie das Komprimierungskennzeichen entfernen (obwohl gzip ziemlich kompakt ist).
Dietbuddha
2
Sie können das Komprimierungsflag auch löschen und stattdessen in SSH ( ssh -Coder Compression yesin ~/.ssh/config) aktivieren .
Sam Hocevar
3
Ich hätte nie gedacht, so einen Teer zu verwenden. Nun, deshalb komme ich her!
Mr. Shickadance
2
Dieser Befehl könnte etwas kürzer sein:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
carlito
2
@ Greg the dash ist eine Konvention in POSIX-kompatibler Software, die je nach Kontext STDIN oder STDOUT bedeutet. Der erste Gedankenstrich bedeutet "aus / dev / stdin lesen" und der zweite - der tatsächlich auf dem entfernten Host ausgeführt wird - "/ dev / stdin". Die Pipe und der SSH verbinden diese beiden Prozesse. Weitere Informationen finden Sie unter unix.stackexchange.com/questions/16357/… .
Richard Metzler
22

Tar mit bzip2-Komprimierung sollte das Netzwerk und die CPU gleichermaßen entlasten.

$ tar -C /path/to/src/dir -jcf - ./ | ssh user@server 'tar -C /path/to/dest/dir -jxf -'

Wird nicht verwendet, -vda die Bildschirmausgabe den Prozess verlangsamen kann. Wenn Sie jedoch eine ausführliche Ausgabe wünschen, verwenden Sie diese auf der lokalen Seite von tar ( -jcvf), nicht auf der Remote-Seite.

Wenn Sie wiederholt über denselben Zielpfad kopieren, z. B. eine Sicherungskopie aktualisieren, empfiehlt es sich, Rsync mit Komprimierung auszuführen.

$ rsync -az -e ssh /path/to/src/dir/ user@server:/path/to/dest/dir/

Beachten Sie, dass sowohl src- als auch dest-Pfade mit einem / enden. Auch hier verwenden Sie -vund -PFlags nicht absichtlich , sondern fügen sie hinzu, wenn Sie eine ausführliche Ausgabe benötigen.

forcefsck
quelle
16

verwenden rsync, verwendet es SSH.

Verwendungszweck:

rsync -aPz /source/path destination.server:remote/path

Die rsync-Switches kümmern sich um die Komprimierung und die I-Node-Informationen. -PZeigt den Fortschritt jeder Datei an.

Sie können verwenden scp -C, was die Komprimierung aktiviert, aber wenn möglich verwenden rsync.

Polemon
quelle
Leider ist rsync auf dem Quellcomputer nicht verfügbar und sshd auch nicht.
Nmichaels
1
sshd ist für diese Vorgänge auf dem Clientcomputer nicht erforderlich.
Polemon
3

Sie können tarmit ssh auf beiden Seiten ausgeführt werden. scpist ein Teil der sshFamilie der Güte, also haben Sie es wahrscheinlich an beiden Enden.

 8:03AM 12 % tar cf - some_directory | ssh dest_host "tar xf -"

Möglicherweise gibt es eine Möglichkeit, gzip oder bzip2 in die Pipeline zu integrieren, um auch den Netzwerkverkehr zu verringern.

Bruce Ediger
quelle
3

@pdos Antwort ist gut, aber man kann die Geschwindigkeit mit einem Puffer und einer guten Komprimierung erhöhen und einen Fortschrittsbalken hinzufügen.

Oft ist das Netzwerk der Engpass und die Geschwindigkeit variiert mit der Zeit. Daher ist es hilfreich, die Daten vor dem Senden über das Netzwerk zu puffern. Dies kann mit erfolgen pv.

Außerdem kann man die Geschwindigkeit normalerweise mit einem geeigneten Komprimierungsalgorithmus erhöhen. Gzip (wie oben verwendet) ist ein schneller Komprimierungsalgorithmus, aber im Allgemeinen komprimiert zstandard ( zstd) (und für hohe Komprimierungsraten LZMA / LZMA2 ( xz)) besser und ist gleichzeitig schneller. Neue xz und zstd unterstützen bereits mehrere Kerne Zur Verwendung von gzip mit mehreren Kernen kann pigz verwendet werden.

Hier ist ein Beispiel zum Senden von Daten mit einem Fortschrittsbalken, Pufferung und zStandard-Komprimierung über ein Netzwerk:

tar cf - . | pv -perabs $(du -sk . | cut -f 1)K | zstd -14 --long=31 -T0 | pv -qCB 512M | ssh user@host "cd /wherever && pv -qCB 512M | zstd -cd -T0 --long=31 | tar xf -"

Der erste pvist, den Fortschritt ( p ), die geschätzte Zeit ( e ), die Übertragungsrate ( r ), die Durchschnittsrate ( a ) und die insgesamt übertragenen Bytes ( b ) anzuzeigen . Die Gesamtgröße wird geschätzt , mit duund auf die Größe Option hinzugefügt ( s ). Der Fortschritt wird vor dem Komprimieren und Puffern gemessen, daher ist er nicht sehr genau, aber dennoch hilfreich.

zstdwird mit der Komprimierungseinstellung 14 verwendet . Diese Anzahl kann je nach Netzwerk und CPU-Geschwindigkeit verringert oder erhöht werden, sodass zstd etwas schneller ist als die Netzwerkgeschwindigkeit. Mit vier Kernen auf einer Haswell-3,2-GHz-CPU erreicht 14 eine Geschwindigkeit von rund 120 MB / s. Im Beispiel wird der lange Modus 31 (verwendet ein 2-GB-Fenster, benötigt viel RAM, ist aber sehr gut, um z. B. Datenbank-Dumps zu komprimieren) verwendet. Mit der Option T0 wird die Anzahl der Threads auf die Anzahl der Kerne festgelegt. Man sollte sich darüber im Klaren sein, dass diese Einstellungen zusammen mit dem Langzeitmodus viel Speicher beanspruchen.

Ein Problem mit zstd ist, dass die meisten Betriebssysteme nicht mit Version> = 1.3.4 ausgeliefert werden. Diese Version ist für eine ordnungsgemäße Unterstützung mit mehreren Kernen und für eine lange Lebensdauer erforderlich. Falls nicht verfügbar, kann es von https://github.com/facebook/zstd mit just kompiliert und installiert werden make -j4 && sudo make install. Anstelle von zstd kann auch xz oder pigz verwendet werden. xz ist langsam, komprimiert aber sehr gut (gut über langsame Verbindungen), pigz / gzip ist schnell, komprimiert aber nicht so gut. pvwird dann wieder verwendet, aber zum Puffern ( qfür leise, Cfür den No-Splice-Modus [immer zum Puffern benötigt] und Bzum Einstellen der Puffergröße).

Im Beispiel wird auch empfängerseitig ein Puffer verwendet. Dies ist häufig unnötig (da die Dekomprimierungs- und Festplatten-Schreibgeschwindigkeit meistens höher ist als die Netzwerkgeschwindigkeit), schadet aber normalerweise auch nicht.

Fabian Heller
quelle
2

Wenn Sie gzip an beiden Enden haben: sourcehost$ cd sourcedir && tar cf - . | gzip -c - | ssh user@destinationhost "cd destinationdir && gzip -c -d | tar xf -"

Wenn Sie kein gzip auf dem Quellcomputer haben, stellen Sie sicher, dass das Ziel dekomprimiert ist: sourcehost$ cd sourcedir && tar cf - . | compress | ssh user@destinationhost "cd destdir && uncompress | tar xf -"

Dies ist schneller, als es zuerst zu komprimieren, dann zu senden und dann zu dekomprimieren, und es erfordert keinen zusätzlichen Speicherplatz auf beiden Seiten. Ich habe die Komprimierungsflagge (z) auf Teer gesetzt, weil Sie sie wahrscheinlich nicht auf der alten Seite haben.

MattBianco
quelle
2

Oder Sie können es umgekehrt tun, wenn Sie müssen. Das heißt, ziehen Sie den Tarball über das Netzwerk, anstatt ihn wie vorgeschlagen zu verschieben. Dies löst den sich wiederholenden Teil Ihrer Frage nicht und rsync ist am besten dafür geeignet, aber es gibt wahrscheinlich TAR-Schalter, die helfen.

Also auf dem lokalen Rechner:

ssh remote 'tar zcf - /etc/resolv.conf' | tar zxf -

Am besten ist es, wenn Sie zuerst im richtigen Verzeichnis sind, oder wenn Sie am Ende den Schalter -C für den Befehl zum Aufheben der Tarierung verwenden.

Nur erwähnen, falls dies benötigt wird. Es ist für mich so, wie in meiner Situation mein lokaler Server hinter nat steckt, also würde es ein bisschen Netzwerkarbeit erfordern, um in der Lage zu sein, es so zu machen, wie es zuvor erwähnt wurde.

HTH

DaveQB
quelle
1

Oder mounten Sie das entfernte Dateisystem über sshfs

sshfs user@remotehost:/path/on/remote /path/on/local
ivanivan
quelle
1

Obwohl es nicht das eleganteste ist, zumal es keine einzelne Zip- oder Tar-Datei kopiert und nicht doppelt, da es nicht dazu beiträgt, das Netzwerk-Overhead zu reduzieren, war meine einzige Wahl scp -r:

-r

      Kopieren Sie rekursiv ganze Verzeichnisse. Beachten Sie, dass scp symbolische Verknüpfungen folgen, die im Tree Traversal auftreten.
Quelle: scp (1)

Ich hatte Probleme mit dem Speicherplatzmangel mit einer 30 GB großen gezippten Teerdatei. Ich dachte, gunzip könnte dies inline tun, dh das Original entfernen, während es entpackt wurde (und ich habe möglicherweise ein Google-Ergebnis verpasst), aber ich konnte nichts finden.

Schließlich, weil ich es müde war, mehrmals darauf zu warten, dass eine neue TAR- oder ZIP-Datei vollständig tariert oder komprimiert wurde, habe ich Folgendes getan:

  1. Navigieren Sie vom ursprünglichen Server / PC / Laptop zu dem Verzeichnis, in dem sich Ihr Ordner mit zahlreichen Dateien / Ordnern befindet.
  2. scp -r source_folder_name yourname@yourservername:destination_folder_name

Dann schnappen Sie sich einfach etwas Bier, Kaffee oder Popcorn und warten. Gut ist, dass scp es erneut versucht, wenn die Netzwerkverbindung "blockiert". Hoffe nur, dass es nicht komplett untergeht.

JGlass
quelle
OK, das kostet deutlich weniger Zeit als die Eingabe von tausend scpBefehlen. Aber die Frage fragt nach "Netzwerk-Overhead". Nutzt Ihre Lösung das Netzwerk weniger, als jede Datei einzeln zu kopieren? Ist Ihre Lösung den sieben bereits veröffentlichten Lösungen in irgendeiner Weise überlegen?
G-Man
Snap, meine schlechte - ich habe den Netzwerk-Overhead-Teil total verpasst - danke für den Hinweis auf @ G-Man. Ich habe die Antwort aktualisiert. Ich halte es immer noch für nützlich, wenn jemand auf ein ähnliches Problem stößt wie ich und wenn ich auf diese Frage gestoßen bin.
JGlass