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

59

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

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

nmichaels
источник

Ответы:

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флагов специально, добавьте их, если вам нужен подробный вывод.

forcefsck
источник
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, потому что он, вероятно, отсутствует на древней стороне.

MattBianco
источник
2

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

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

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

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

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

НТН

DaveQB
источник
1

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

sshfs user@remotehost:/path/on/remote /path/on/local
ivanivan
источник
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 будет повторять попытки, если сетевое соединение "зависнет". Просто надеюсь, что это не пройдет полностью.

JGlass
источник
Хорошо, это явно занимает меньше времени, чем ввод тысячи scpкоманд. Но вопрос задается о «издержках сети». Использует ли ваше решение сеть меньше, чем копирует каждый файл по отдельности? Ваше решение превосходит семерку, которая уже была опубликована?
G-Man говорит: «Восстановите Монику»
Хватит, мой плохой - я полностью пропустил сетевую часть - спасибо за то, что указал на @ G-Man. Я обновил ответ, я все еще чувствую, что может быть полезно, если кто-то сталкивается с подобной проблемой, как я, и когда я наткнулся на этот вопрос.
JGlass