Jak najlepiej skopiować dużą liczbę małych plików na scp?

59

Mam katalog, który ma kilka gigabajtów i kilka tysięcy małych plików. Chcę skopiować go przez sieć z SCP więcej niż raz. Czas procesora na komputerach źródłowych i docelowych jest tani, ale obciążenie sieci związane z kopiowaniem każdego pliku osobno jest ogromne. Zrobiłbym to tar / gzip i wysłałem, ale na komputerze źródłowym brakuje dysku.

Czy jest dla mnie sposób na przesyłanie danych wyjściowych tar -czf <output> <directory>do scp? Jeśli nie, czy istnieje inne łatwe rozwiązanie? Moja maszyna źródłowa jest starożytna (SunOS), więc wolałbym nie instalować na niej różnych rzeczy.

nmichaels
źródło

Odpowiedzi:

104

Możesz przesyłać tar do sesji ssh:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"
pdo
źródło
3
+1 rozwiązanie smoły Jeśli masz większą przepustowość i mniej procesora, możesz usunąć flagę kompresji (chociaż gzip jest dość lekki).
dietbuddha 24.03.11
2
I możesz upuścić flagę kompresji i zamiast tego aktywować ją w SSH ( ssh -Club Compression yesw ~/.ssh/config).
sam hocevar,
3
Nigdy nie myślałem o użyciu tar tak. Właśnie dlatego tu przychodzę!
Pan Shickadance,
2
Polecenie można nieco skrócić:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
carlito
2
@Greg myślnik to konwencja w oprogramowaniu zgodnym z POSIX, oznaczająca STDIN lub STDOUT w zależności od kontekstu. Pierwszy myślnik oznacza „odczyt z / dev / stdin”, a drugi - który jest faktycznie wykonywany na zdalnym hoście - oznacza „/ dev / stdin”. Rura i ssh łączą oba te procesy. Zobacz unix.stackexchange.com/questions/16357/..., aby dowiedzieć się więcej.
Richard Metzler
22

Tar z kompresją bzip2 powinien pobrać tyle samo obciążenia z sieci i na procesor.

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

Nie używa, -vponieważ wyświetlanie ekranu może spowolnić proces. Ale jeśli chcesz uzyskać pełne wyjście, użyj go po lokalnej stronie tar ( -jcvf), a nie na zdalnej części.

Jeśli wielokrotnie kopiujesz tę samą ścieżkę docelową, na przykład aktualizując kopię zapasową, najlepszym wyborem jest rsync z kompresją.

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

Zauważ, że ścieżki src i dest kończą się znakiem /. Ponownie, nie używając -vi -Pflagi celowo, dodaj je, jeśli potrzebujesz pełnych danych wyjściowych.

forcefsck
źródło
16

użyj rsync, używa SSH.

Stosowanie:

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

Przełączniki rsync dbają o kompresję i informacje o I-Node. -Pwyświetla postęp każdego pliku.

Możesz użyć scp -C, który umożliwia kompresję, ale jeśli to możliwe, użyj rsync.

polemon
źródło
Niestety rsync nie jest dostępny na maszynie źródłowej, podobnie jak sshd.
nmichaels
1
sshd nie jest konieczny do tych operacji na komputerze klienckim.
polemon
3

Możesz uruchomić tarna obu końcach za pomocą ssh. scpjest częścią sshrodziny dobroci, więc prawdopodobnie masz ją po obu stronach.

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

Może istnieć sposób pracy z gzip lub bzip2 w potoku, aby również zmniejszyć ruch w sieci.

Bruce Ediger
źródło
3

Odpowiedź @ pdo jest dobra, ale można zwiększyć prędkość za pomocą bufora i dobrej kompresji oraz dodać pasek postępu.

Często sieć stanowi wąskie gardło, a prędkość zmienia się w czasie. Dlatego pomaga buforować dane przed wysłaniem ich przez sieć. Można to zrobić za pomocą pv.

Ponadto zwykle można zwiększyć prędkość za pomocą odpowiedniego algorytmu kompresji. Gzip (jak używany powyżej) jest algorytmem szybkiej kompresji, ale generalnie zstandard ( zstd) (i dla wysokich współczynników kompresji LZMA / LZMA2 ( xz) będzie kompresował się lepiej i był szybszy w tym samym czasie. Nowe Xz i Zstd mają już wbudowaną obsługę wielu rdzeni Aby użyć gzip z wieloma rdzeniami, można użyć Pigza.

Oto przykład wysyłania danych z paskiem postępu, buforowaniem i standardową kompresją przez sieć:

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 -"

Pierwszym pvjest pokazanie postępu ( p ), szacowanego czasu ( e ), szybkości transferu ( r ), średniej prędkości ( a ), całkowitej liczby przesłanych bajtów ( b ). Całkowita wielkość szacuje się dui dodaje do wyboru (rozmiar s ). Postęp jest mierzony przed kompresją i buforowaniem, dlatego nie jest zbyt dokładny, ale nadal jest pomocny.

zstdjest używany z ustawieniem kompresji 14 . Liczba ta może zostać zmniejszona lub zwiększona w zależności od prędkości sieci i procesora, więc zstd jest nieco szybszy niż prędkość sieci. Z czterema rdzeniami procesora Haswell 3.2 GHz 14 daje prędkość około 120 MB / s. W tym przykładzie użyto trybu długiego 31 (używa okna 2 GB, wymaga dużo pamięci RAM, ale bardzo dobrze np. Do kompresji zrzutów bazy danych). W T0 Opcje ustawia ilość wątków z liczbą rdzeni. Należy pamiętać, że wraz z długim trybem ustawienia te zajmują dużo pamięci.

Problem z ZSTD polega na tym, że większość systemów operacyjnych nie jest dostarczana z wersją> = 1.3.4. Ta wersja jest niezbędna do prawidłowego obsługi wielu rdzeni i długiego wsparcia. Jeśli nie jest dostępny, można go skompilować i zainstalować z https://github.com/facebook/zstd za pomocą just make -j4 && sudo make install. Zamiast ZSTD można również użyć XZ lub Pigz. xz jest wolny, ale bardzo dobrze kompresuje (dobry przy wolnych połączeniach), pigz / gzip jest szybki, ale nie tak dobrze. pvjest następnie używane ponownie, ale do buforowania ( qdla cichej, Cdla trybu bez łączenia [zawsze potrzebne do buforowania] i Bdo ustawienia wielkości bufora).

W tym przykładzie bufor jest również używany po stronie odbiornika. Jest to często niepotrzebne (ponieważ szybkość dekompresji i zapisu na dysku twardym jest w większości przypadków wyższa niż prędkość sieci), ale zwykle też nie szkodzi.

Fabian Heller
źródło
2

Jeśli masz gzip na obu końcach: sourcehost$ cd sourcedir && tar cf - . | gzip -c - | ssh user@destinationhost "cd destinationdir && gzip -c -d | tar xf -"

Jeśli nie masz gzip na maszynie źródłowej, upewnij się, że rozpakowałeś w miejscu docelowym: sourcehost$ cd sourcedir && tar cf - . | compress | ssh user@destinationhost "cd destdir && uncompress | tar xf -"

Byłoby to szybsze niż najpierw skompresowanie go, a następnie wysłanie, a następnie rozpakowanie, i nie wymaga dodatkowego miejsca na dysku po obu stronach. Wytarłem flagę kompresji (z) na tar, ponieważ prawdopodobnie nie masz jej po starożytnej stronie.

MattBianco
źródło
2

Lub możesz to zrobić na odwrót, jeśli potrzebujesz. To jest ściąganie tarballa przez sieć zamiast przepychania go, jak sugerowano. To nie rozwiązuje powtarzającej się części twojego pytania i rsync jest do tego najlepszy, ale prawdopodobnie są do tego przełączniki tar.

Na komputerze lokalnym:

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

Najlepiej jest najpierw znaleźć się w odpowiednim katalogu, w przeciwnym razie musisz użyć przełącznika -C na poleceniu odznaczania na końcu.

Wystarczy wspomnieć o tym w razie potrzeby. Jest to dla mnie, ponieważ w mojej sytuacji mój lokalny serwer jest za nat, więc zajęłoby to trochę sieci, aby móc to zrobić tak, jak wcześniej wspomniano.

HTH

DaveQB
źródło
1

Lub zamontuj zdalny system plików za pomocą sshfs

sshfs user@remotehost:/path/on/remote /path/on/local
ivanivan
źródło
1

Chociaż nie jest to najbardziej eleganckie, zwłaszcza, że ​​nie kopiuje pojedynczego pliku zip lub tar i podwójnie, ponieważ nie pomaga zmniejszyć przepełnienia sieci, moim jedynym wyborem było użycie scp -r:

-r

      Rekurencyjnie kopiuj całe katalogi. Zauważ, że scp podążają za dowiązaniami symbolicznymi napotkanymi podczas przechodzenia przez drzewo.
Źródło: scp (1)

Wystąpiły problemy z brakiem miejsca na dysku w pliku tar o rozmiarze 30 GB. Myślałem, że gunzip mógłby to zrobić inline, tj. Usuwając oryginał, ponieważ był rozpakowywany (i mogłem przegapić wynik Google), ale nic nie mogłem znaleźć.

Wreszcie, ponieważ miałem dość wielokrotnego czekania na nowy plik TAR lub ZIP, aby zakończyć tarowanie lub kompresowanie, w końcu właśnie to zrobiłem:

  1. Z oryginalnego serwera / komputera / laptopa przejdź do katalogu, w którym znajduje się folder z wieloma plikami / folderami.
  2. scp -r source_folder_name yourname@yourservername:destination_folder_name

Następnie weź piwo, kawę lub popcorn i poczekaj. Dobrą rzeczą jest to, że scp spróbuje ponownie, jeśli połączenie sieciowe „utknie”. Mam tylko nadzieję, że nie spadnie całkowicie.

JGlass
źródło
OK, to wyraźnie zajmuje mniej czasu niż wpisywanie tysiąca scppoleceń. Ale pytanie dotyczy „obciążenia sieci”. Czy Twoje rozwiązanie korzysta z sieci mniej niż kopiowanie każdego pliku osobno? Czy twoje rozwiązanie jest lepsze w jakikolwiek sposób od siedmiu, które już zostały opublikowane?
G-Man,
Snap, moja zła - całkowicie przegapiłem część sieciową - dzięki za zwrócenie na to uwagi @ G-Man. Zaktualizowałem odpowiedź, nadal uważam, że przydałoby się, gdyby ktoś napotkał podobny problem jak ja i kiedy natknąłem się na to pytanie.
JGlass