Як я можу найкраще скопіювати велику кількість невеликих файлів через scp?


59

У мене є каталог, який має кілька гігабайт і кілька тисяч невеликих файлів. Я хочу скопіювати його через мережу з scp не один раз. Час процесора на джерелах та машинах призначення дешевий, але мережеві накладні витрати, копіювані кожен файл окремо, величезні. Я б таргував / gzip і відправляв його, але джерело не вистачає на диску.

Чи є спосіб, щоб я передав висновок tar -czf <output> <directory>scp? Якщо ні, чи є ще одне просте рішення? Моя джерельна машина є давньою (SunOS), тому я не хотів би встановлювати на ній речі.

Відповіді:


104

Ви можете передавати tar на протязі сеансу ssh:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"

3
+1 розчин дьогтю. Якщо у вас більше пропускної здатності і менше процесора, ви можете зняти прапор стиснення (хоча gzip досить легкий).
дієтабудда

2
Ви можете скинути прапор стиснення і замість цього активувати його в SSH ( ssh -Cабо Compression yesв ~/.ssh/config).
sam hocevar

3
Ніколи не думав використовувати такий дьоготь. Ну, ось чому я приходжу сюди!
Містер Шикаданс

2
Цю команду можна було зробити трохи коротшою:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
carlito

2
@Greg тире - це умова в сумісному програмному забезпеченні POSIX, що означає STDIN або STDOUT залежно від контексту. Перший тире означає "читати з / dev / stdin", а другий - який фактично виконується на віддаленому хості - означає "/ dev / stdin". Труба і ssh з'єднують ці обидва процеси. Дивіться unix.stackexchange.com/questions/16357/…, щоб дізнатися більше.
Річард Метцлер

22

Тар з стисненням bzip2 повинен зняти стільки, скільки навантаження на мережу та на процесор.

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

Не використовується, -vоскільки вихід на екран може уповільнити процес. Але якщо ви хочете багатослівний вихід, використовуйте його на локальній стороні tar ( -jcvf), а не на віддаленій частині.

Якщо ви неодноразово копіюєте через той самий шлях призначення, як-от оновлення резервної копії, ваш найкращий вибір - rsync із стисненням.

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

Зауважте, що і src, і dest шляху закінчуються a /. Знову ж таки, не використовуючи -vі -Pпрапори за призначенням, додайте їх, якщо вам потрібен багатослівний вихід.


16

використання rsync, він використовує SSH.

Використання:

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

Перемикачі rsync дбають про стиснення та інформацію про I-вузол. -Pвідображає хід кожного файлу.

Можна використовувати scp -C, що дозволяє стиснути, але, якщо можливо, використовувати rsync.


На жаль, rsync недоступний на вихідній машині, а також sshd.
nmichaels

1
sshd не потрібен для цих операцій на клієнтській машині.
полемон

3

Ви можете працювати tarз обох кінців за допомогою ssh. scpє частиною sshродини добра, тож ви, мабуть, маєте її з обох кінців.

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

Можливо, існує спосіб роботи gzip або bzip2 в трубопроводі, щоб зменшити мережевий трафік.


3

@ pdo відповідь хороша, але можна збільшити швидкість за допомогою буфера та хорошого стиснення та додати смугу прогресу.

Часто мережа є вузьким місцем, і швидкість змінюється з часом. Тому він допомагає зберігати дані перед тим, як надсилати їх по мережі. Це можна зробити за допомогою pv.

Крім того, зазвичай можна збільшувати швидкість за допомогою відповідного алгоритму стиснення. Gzip (як і раніше) - це алгоритм швидкого стиснення, але загалом zstandard ( zstd) (і для високих коефіцієнтів стиснення LZMA / LZMA2 ( xz) буде стискатися краще і бути швидшим за той самий час. Нові xz та zstd мають вже вбудовану багатоядерну підтримку Для використання gzip з декількома ядрами може використовуватися pigz.

Ось приклад для надсилання даних з панеллю прогресу, буферизацією та стисканням zstandard по мережі:

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

Перший pv- показати прогрес ( p ), орієнтовний час ( e ), швидкість передачі ( r ), середню швидкість ( a ), загальну кількість переданих байтів ( b ). Загальний розмір оцінюється з duі додається до опції (розмір и ). Прогрес вимірюється до стиснення та буферизації, тому це не дуже точно, але все ж корисно.

zstdвикористовується з налаштуванням стиснення 14 . Це число можна зменшити або збільшити залежно від мережі та швидкості процесора, тому zstd трохи швидше, ніж швидкість мережі. З чотирма ядрами на процесорі Haswell 3,2 ГГц процесор 14 забезпечує швидкість близько 120 Мб / с. У прикладі використовується довгий режим 31 (використовує вікно 2 Гб, потребує великої кількості оперативної пам’яті, але дуже добре, наприклад для стиснення відвалів баз даних). Параметри T0 встановлюють кількість потоків на кількість ядер. Слід пам’ятати, що разом із тривалим режимом ці налаштування використовують багато пам’яті.

Проблема zstd полягає в тому, що більшість операційних систем не постачається з версією> = 1.3.4. Ця версія необхідна для належної багатоядерної та тривалої підтримки. Якщо він недоступний, його можна скласти та встановити з https://github.com/facebook/zstd просто make -j4 && sudo make install. Замість zstd можна також використовувати xz або pigz. xz повільний, але стискає дуже добре (добре при повільних з'єднаннях), pigz / gzip швидкий, але стискає не так добре. pvпотім використовується знову, але для буферизації ( qдля тихого, Cдля режиму без сплайсингу (завжди потрібен для буферизації) та Bдля встановлення розміру буфера).

У прикладі буфер також використовується на стороні приймача. Це часто є непотрібним (оскільки швидкість декомпресії та запису на жорсткий диск у більшості разів перевищує швидкість мережі), але, як правило, теж не шкодить.


2

Якщо у вас є gzip з обох кінців: sourcehost$ cd sourcedir && tar cf - . | gzip -c - | ssh user@destinationhost "cd destinationdir && gzip -c -d | tar xf -"

Якщо у вас не встановлено gzip на вихідному апараті, переконайтесь, що ви знімаєте компресію в пункті призначення: sourcehost$ cd sourcedir && tar cf - . | compress | ssh user@destinationhost "cd destdir && uncompress | tar xf -"

Це буде швидше, ніж спочатку застебнути його, потім надіслати, потім розпакувати, і це не потребує додаткового місця на диску з обох сторін. Я похилив прапор стиснення (z) на дьогті, тому що ви, мабуть, не маєте його на стародавній стороні.


2

Або ви можете зробити це навпаки, якщо вам потрібно. Це пропонується перетягнути тарбол по мережі, а не натискати, як було запропоновано. Це не вирішує повторювану частину вашого питання, і rsync найкраще підходить для цього, але, ймовірно, є перемикачі смоли на допомогу.

Отже, на локальній машині:

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

Найкраще спочатку знаходитись у правильному каталозі, або потрібно скористатися перемикачем -C у команді untaring наприкінці.

Просто згадуючи це у випадку, якщо це потрібно. Це для мене, як і в моїй ситуації, мій локальний сервер відстає від nat, тому потрібен буде якийсь мережевий фетшинг, який зможе зробити це так, як згадувалося раніше.

HTH


1

Або змонтуйте віддалену файлову систему через sshfs

sshfs user@remotehost:/path/on/remote /path/on/local

1

Хоча це не найелегантніше, тим більше, що це не копіювання файлу жодного zip або tar та подвійно, оскільки це не допомагає зменшити накладні витрати в мережі, моїм єдиним вибором було використання scp -r:

-r

      Рекурсивно копіюйте цілі каталоги. Зауважте, що scp слідують символічні посилання, що зустрічаються в обході дерева.
Джерело: scp (1)

У мене виникли проблеми, у яких не вистачає місця на диску з 30-ГБ-накопичувальним файлом tar. Я думав, що gunzip може зробити це вбудованим шляхом, тобто видалити оригінал, як він був розпакований (і, можливо, я пропустив результат Google), але я нічого не міг знайти.

Нарешті, оскільки мені набридло багато разів намагатися чекати, коли новий файл TAR або ZIP закінчиться таргінгуванням або блискавкою, я нарешті тільки що зробив:

  1. З оригінального сервера / ПК / ноутбука перейдіть до каталогу, де знаходиться ваша папка з численними файлами / папками.
  2. scp -r source_folder_name yourname@yourservername:destination_folder_name

Тоді просто візьміть трохи пива, кави чи попкорну та почекайте. Хороша річ, що scp повторить спробу, якщо мережеве з'єднання "зупиниться". Просто сподівайтеся, що вона не знизиться повністю.


Гаразд, це явно займає менше часу, ніж набравши тисячу scpкоманд. Але питання задається питанням про "мережеві накладні витрати". Чи ваше рішення використовує мережу менше, ніж копіювати кожен файл окремо? Чи вашим рішенням будь-яким чином перевершує семи, які вже були розміщені?
G-Man

Оснащення, моє погано - я зовсім пропустив накладну частину мережі - дякую, що вказав на це @ G-Man. Я оновив відповідь, я все ще вважаю, що це може бути корисним, якщо хтось натрапить на подібну проблему, як я, і коли я натрапив на це питання.
JGlass
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.