Назад | Перейти на главную страницу

Как распараллелить команду 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

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

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

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

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

Распараллеливание 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 ) &

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

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

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

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

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

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