Какой лучший способ выполнить параллельное копирование в Unix?

18

Мне обычно приходится копировать содержимое папки в сетевой файловой системе на мой локальный компьютер. В удаленной папке есть много файлов (1000 с), которые все относительно малы, но из-за сетевых издержек обычное копирование cp remote_folder/* ~/local_folder/занимает очень много времени (10 минут).

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

Какой самый простой способ увеличить скорость этой копии? (Я предполагаю, что это будет выполнять копию параллельно.)

Архивирование файлов перед копированием не обязательно ускорит процесс, поскольку все они могут быть сохранены на разных дисках на разных серверах.

DSG
источник
Архивирование файлов перед копированием значительно ускорит процесс, потому что больше не нужно будет, «вы получили этот файл», «да, я сделал», «вот следующий», «хорошо», ... Это те «Обороты», которые замедляют вас.
Дэвид Шварц
Вероятно, это ограничивающий фактор, скорее скорость диска, чем скорость сети, и если это так, то параллельное выполнение этого для каждого файла замедлит работу , а не ускорит, потому что вы заставите диск постоянно выполнять поиск назад и вперед. между файлами.
Джоэл Кохорн
Хотя архивирование может быть не очень хорошей идеей (запуск сжатия более 1000 файлов может занять некоторое время), tar может быть жизнеспособным.
Роб
@JoelCoehoorn все же, есть случаи, когда это не так: например, несколько шпинделей + небольшие файлы (или просто случайное чтение). В этом случае "параллельный cp" поможет.
CAFxX

Ответы:

8

Пока вы ограничиваете команды копирования, которые вы выполняете, вы, вероятно, можете использовать скрипт, подобный тому, который опубликовал Scrutinizer.

SOURCEDIR="$1"
TARGETDIR="$2"
MAX_PARALLEL=4
nroffiles=$(ls "$SOURCEDIR" | wc -w)
setsize=$(( nroffiles/MAX_PARALLEL + 1 ))
ls -1 "$SOURCEDIR"/* | xargs -n "$setsize" | while read workset; do
  cp -p "$workset" "$TARGETDIR" &
done
wait
OldWolf
источник
1
Примечание предупреждения, хотя: этот сценарий разрывается с именами файлов, содержащими пробелы или символы-заглушки.
Slhck
@OldWolf - Можете ли вы объяснить, как работает этот скрипт? Например, какую часть выполняет распараллеливание?
DSG
3
@dsg: &в конце cpкоманды позволяет whileциклу продолжить и запустить следующую команду cp без ожидания. Команда xargsпередает имена файлов в группах по 4 (MAX_PARALLEL) в whileцикл.
RedGrittyBrick
Не работает для меня Я не уверен, что это возможно, чтобы ускорить cp. Вы, конечно, можете ускорить расчет через многопоточность. Но я не думаю, что то же самое относится и к копированию данных на жестком диске.
Adobe
9

Если у вас установлен GNU Parallel http://www.gnu.org/software/parallel/, вы можете сделать это:

parallel -j10 cp {} destdir/ ::: *

Вы можете установить GNU Parallel просто:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 3374ec53bacb199b245af2dda86df6c9
12345678 3374ec53 bacb199b 245af2dd a86df6c9
$ md5sum install.sh | grep 029a9ac06e8b5bc6052eac57b2c3c9ca
029a9ac0 6e8b5bc6 052eac57 b2c3c9ca
$ sha512sum install.sh | grep f517006d9897747bed8a4694b1acba1b
40f53af6 9e20dae5 713ba06c f517006d 9897747b ed8a4694 b1acba1b 1464beb4
60055629 3f2356f3 3e9c4e3c 76e3f3af a9db4b32 bd33322b 975696fc e6b23cfb
$ bash install.sh

Посмотрите вступительные видео для GNU Parallel, чтобы узнать больше: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Оле Танге
источник
3

Одним из способов будет использование rsync, который будет копировать только изменения - новые файлы и измененные части других файлов.

http://linux.die.net/man/1/rsync

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

Linker3000
источник
2

Честно говоря, лучший инструмент - это gsutil от Google. Он обрабатывает параллельные копии с рекурсией каталога. Большинство других методов, которые я видел, не могут справиться с рекурсией каталога. Они специально не упоминают локальную файловую систему к локальным копиям файловой системы в своих документах, но это работает как шарм.

Это еще один двоичный файл для установки, но, вероятно, тот, который вы уже можете запустить, учитывая все современные внедрения облачных сервисов.

ВИК
источник
2

Параллельный rsync с использованием find:

export SOURCE_DIR=/a/path/to/nowhere
export DEST_DIR=/another/path/to/nowhere

# sync folder structure first
rsync -a -f'+ */' -f'- *' $SOURCE_DIR $DEST_DIR

# cwd
cd $SOURCE_DIR

# use find to help filter files etc. into list and pipe into gnu parallel to run 4 rsync jobs simultaneously
find . -type f | SHELL=/bin/sh parallel --linebuffer --jobs=4 'rsync -av {} $DEST_DIR/{//}/'

в корпоративной локальной сети одиночная rsync выполняет около 800 Мбит / с; с 6-8 работами я могу получить более 2,5 Гбит / с (за счет высокой нагрузки). Ограничено дисками.

yee379
источник
0

Есть много вещей, которые нужно учитывать в зависимости от имеющейся у вас топологии. Но прежде чем начать думать о сложных решениях, вы можете просто попытаться разделить задачу на две работы и проверить, не сократится ли необходимое время:

В следующий раз попробуйте:

  cp remote_folder/[a-l]* ~/local_folder/ &
  cp remote_folder/[!a-l]* ~/local_folder/ &
  wait
  wait

(вы можете заменить [al] * на что-то еще, что соответствует примерно половине файлов - возможно, [0-4] * - в зависимости от содержимого папки)

Если время не улучшается значительно, может быть более важно проверить, необходимо ли копировать все файлы (каково соотношение измененных файлов ко всем файлам?)

КТФ
источник