Как распараллелить команду scp?

Как распараллелить команду scp?

Мне нужно scp файлы из machineBи machineCв machineA. Я запускаю свой скрипт оболочки ниже из machineA. Я правильно настроил ключи ssh.

Если файлов нет в machineB, то они должны быть в machineC. Мне нужно переместить все ФАЙЛЫ PARTITION1 И PARTITION2 в соответствующую папку machineA, как показано ниже в моем скрипте оболочки -

#!/bin/bash

readonly PRIMARY=/export/home/david/dist/primary
readonly SECONDARY=/export/home/david/dist/secondary
readonly FILERS_LOCATION=(machineB machineC)
readonly MAPPED_LOCATION=/bat/data/snapshot
PARTITION1=(0 3 5 7 9)
PARTITION2=(1 2 4 6 8)

dir1=$(ssh -o "StrictHostKeyChecking no" david@${FILERS_LOCATION[0]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
dir2=$(ssh -o "StrictHostKeyChecking no" david@${FILERS_LOCATION[1]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)

length1=$(ssh -o "StrictHostKeyChecking no" david@${FILERS_LOCATION[0]} "ls '$dir1' | wc -l")
length2=$(ssh -o "StrictHostKeyChecking no" david@${FILERS_LOCATION[1]} "ls '$dir2' | wc -l")

if [ "$dir1" = "$dir2" ] && [ "$length1" -gt 0 ] && [ "$length2" -gt 0 ]
then
    rm -r $PRIMARY/*
    rm -r $SECONDARY/*
    for el in "${PARTITION1[@]}"
    do
        scp david@${FILERS_LOCATION[0]}:$dir1/t1_weekly_1680_"$el"_200003_5.data $PRIMARY/. || scp david@${FILERS_LOCATION[1]}:$dir2/t1_weekly_1680_"$el"_200003_5.data $PRIMARY/.
    done
    for sl in "${PARTITION2[@]}"
    do    
        scp david@${FILERS_LOCATION[0]}:$dir1/t1_weekly_1680_"$sl"_200003_5.data $SECONDARY/. || scp david@${FILERS_LOCATION[1]}:$dir2/t1_weekly_1680_"$sl"_200003_5.data $SECONDARY/.
    done
fi

В настоящее время у меня есть 5 файлов в PARTITION1 и PARTITION2, но в целом там будет около 420 файлов, так что это означает, что он будет перемещать файлы по одному, что, я думаю, может быть довольно медленно. Есть ли способ ускорить процесс?

Я использую Ubuntu 12.04.

решение1

Распараллеливание SCP контрпродуктивно, если только обе стороны не работают на SSD. Самая медленная часть SCP — это сеть, в этом случае распараллеливание вообще не поможет, или диски на обеих сторонах, которые вы только усугубите распараллеливанием: время поиска вас убьет.

Вы говорите, что machineA находится на SSD, поэтому распараллеливания на машину должно быть достаточно. Самый простой способ сделать это — обернуть первый forloop в подоболочку и сделать его фоновым.

( for el in "${PARTITION1[@]}"
do
    scp david@${FILERS_LOCATION[0]}:$dir1/t1_weekly_1680_"$el"_200003_5.data $PRIMARY/. || scp david@${FILERS_LOCATION[1]}:$dir2/t1_weekly_1680_"$el"_200003_5.data $PRIMARY/.
done ) &

решение2

Вы можете использовать GNU Parallel для параллельного выполнения нескольких задач.

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

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

Если rsync недоступен, в качестве альтернативы можно использовать zip, или даже tarи gzipили bzip2, а затем scpполученные архивы (затем подключиться с помощью sshи выполнить распаковку).

решение3

У меня уже была проблема с SCP: две машины в одной сети с гигабитным соединением передавали данные по SCP очень медленно.

Если вам НЕ нужно шифрование, то наверняка немного поможет использование ftp или nfs.

Я выяснил, что проблема была в том, что у одной из машин была медленная оперативная память, а шифрование ssh было очень требовательным для этой машины. Использование ftp или nfs решило мою проблему, я поднял скорость с 15-20 МБ/с до 100+ МБ/с.

[РЕДАКТИРОВАТЬ]

Я только что нашел это, которое использует отличный rsync вместо scp. Это не решит всю вашу проблему, но может помочь.

https://gist.github.com/KartikTalwar/4393116

Связанный контент