Как я могу лучше всего скопировать большое количество маленьких файлов по scp?


59

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

Есть ли способ для меня, чтобы передать вывод tar -czf <output> <directory>scp? Если нет, есть ли другое простое решение? Моя исходная машина старая (SunOS), поэтому я бы не стал устанавливать на нее какие-либо вещи.

Ответы:


104

Вы можете передать tar через сессию ssh:

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

3
+1 смоляное решение. Если у вас больше пропускная способность и меньше ЦП, вы можете убрать флаг сжатия (хотя gzip довольно легкий).
dietbuddha

2
И вы можете сбросить флаг сжатия и вместо этого активировать его в SSH ( ssh -Cили Compression yesв ~/.ssh/config).
Сэм Хоцевар

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

2
Эту команду можно сделать несколько короче:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
Карлито

2
@Greg the dash - это соглашение в POSIX-совместимом программном обеспечении, обозначающее STDIN или STDOUT в зависимости от контекста. Первый тире означает «чтение из / dev / stdin», а второй - который фактически выполняется на удаленном хосте - означает «/ dev / stdin». Труба и ssh соединяют эти оба процесса. См. Unix.stackexchange.com/questions/16357/… чтобы узнать больше.
Ричард Метцлер

22

Tar со сжатием 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 заканчиваются символом /. Опять же, без использования -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 с помощью just 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) на tar, потому что он, вероятно, отсутствует на древней стороне.


2

Или вы можете сделать это наоборот, если вам нужно. То есть перетаскивать архив по сети, а не выдвигать его, как было предложено. Это не решает повторяющуюся часть вашего вопроса, и для этого лучше всего подойдет rsync, но, вероятно, есть ключи tar, чтобы помочь.

Итак, на локальной машине:

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

Лучше всего сначала оказаться в нужном каталоге, либо в конце вы должны использовать ключ -C команды unntaring.

Просто упомянуть об этом на случай, если это необходимо. Это для меня, так как в моей ситуации мой локальный сервер отстает от nat, поэтому потребовалось бы некоторое сетевое размышление, чтобы иметь возможность сделать это так, как было упомянуто ранее.

НТН


1

Или смонтируйте удаленную файловую систему через sshfs

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

1

Хотя это и не самый элегантный вариант, тем более что он не копирует один zip-файл или tar-файл и вдвойне, так как это не помогает уменьшить нагрузку на сеть, мой единственный выбор был использовать scp -r:

-r

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

У меня были проблемы с нехваткой места на диске с архивным файлом 30 ГБ. Я думал, что 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.