Распараллеливание удаленного tar и получение вывода по каналу ssh

467
Johnny_Bit

Я пытался распараллелить сценарий, который я использую, но пока что GNU Parallel очень сложен.

У меня есть 2 файла - один, содержащий хосты для запуска команды, а второй с параметрами для команды. Ниже приведены примеры данных:

$ cat workers.host  foo@192.168.0.7 bar@192.168.0.8 jerry@192.168.0.9 tom@192.168.0.21    $ cat paths /usr/local/jar/x/y/ jarxy /usr/local/jar/z/y/ jarzy /usr/local/jar/y/y/ jaryy /usr/local/far/x/y/ farxy /usr/local/jaz/z/z/ jazzz /usr/local/mu/txt/ana/ acc01 /usr/local/jbr/x/y/ accxy 

И чтобы обработать это, я использую следующий скрипт:

#!/bin/bash  echo "Run this on 192.168.130.10";  DATA=`date +%F` DDAY=`date +%u` DOMBAC='nice tar cpzf'  readarray -t hosts < workers.host  len=${#hosts[@]}; processed=0;  while read -r -a line; do  let hostnum=processed%len;  ssh $ -i /root/.ssh/id_rsa "$DOMBAC - $" > "/data/backup/$DDAY/$_$_FULL.tgz"  let processed+=1; done < paths 

Это работает хорошо, однако обрабатывает шаг за шагом на машине за машиной. Хосты достаточно мощные, и сеть здесь не проблема, поэтому я хотел максимально распараллелить это. Например, запустите 4 экземпляра команды tar на каждом хосте и передайте через ssh файл с правильным именем. Я полностью потерян с параллелью --results --sshloginfile... И в конечном итоге я пытаюсь выполнить 4 задания на каждом хосте, каждое с разными параметрами (чтобы, например, хост 2 не переписывал то, что хост 1 уже сделал), Можно ли это сделать в GNU Parallel?

1

2 ответа на вопрос

1
Ole Tange

Для начала вам нужно знать, как извлечь несколько аргументов из одной строки ввода:

cat paths | parallel --colsep ' ' echo == 

(Я отмечаю, что некоторые из могут быть сгенерированы из . Если это всегда так, вы можете захотеть взглянуть на {= =}; но это история для другого вопроса).

Для удаленного запуска заданий вы используете -S:

cat paths | parallel --colsep ' ' -S server echo == 

Чтобы контролировать, сколько заданий выполняется на удаленном сервере, используйте -j:

cat paths | parallel --colsep ' ' -j4 -S server echo == 

Чтобы получить вывод, сохраненный локально, --return --cleanupможно использовать:

cat paths | parallel --return --cleanup --colsep ' ' -j4 -S server echo == '>' 

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

cat paths | parallel --return my/local/dir/./ --cleanup --colsep ' ' -j4 -S server echo == '>' 

Чтобы использовать специальную sshкоманду, используйте --ssh:

parallel --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return --cleanup --colsep ' ' -j4 -S server echo == '>' 

Для запуска на нескольких серверах используйте --slfвместо -S:

parallel --slf hosts.txt --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return --cleanup --colsep ' ' -j4 echo == '>' 

В общем, ваша команда может выглядеть так:

parallel --slf hosts.txt --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return /data/backup/$DDAY/./_$_FULL.tgz --cleanup --colsep ' ' -j4 "$DOMBAC - > _$_FULL.tgz" 
Комментарии переполнения стека не подходят для совместного использования кода и обсуждения;) В любом случае - мне нужно попробовать Ваше решение. Моя текущая (грубая) основывается на двух вещах: `parallel -j $ --link ./do_on_hosts.sh " $ DATA "" $ DDAY ":::: worker.host :: :: to_backup.path` и в do_on_hosts.sh: `ssh $ 1" $ $ "> $ $ / $ _ $ _FULL.tgz` Интересно, как это соотносится с твоим ... нужен еще один раунд, чтобы попробовать. Johnny_Bit 7 лет назад 0
0
Argonauts

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

Чтобы сделать это с минимальными изменениями в вашем существующем скрипте, все, что нам нужно сделать, это выполнить фон каждой задачи во время ее выполнения (для этого используется оператор &). Чтобы предотвратить потерянные процессы, мы должны убедиться, что скрипт не завершится, пока все задания не будут завершены, что выполняется с помощью встроенной команды bash wait. Команда jobs выдает список запущенных задач (может быть, не все из них, некоторые, возможно, уже закончили, пока вы не достигли этого места, в зависимости от времени выполнения).

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

Вот модифицированная версия вашего скрипта с этими изменениями

#!/bin/bash  echo "Run this on 192.168.130.10";  DATA=`date +%F` DDAY=`date +%u` DOMBAC='nice tar cpzf'  readarray -t hosts < workers.host  len=${#hosts[@]}; processed=0;  while read -r -a line; do  let hostnum=processed%len;  ssh $ -i /root/.ssh/id_rsa "$DOMBAC - $" > "/data/backup/$DDAY/$_$_FULL.tgz" &  let processed+=1; done < paths jobs wait 
Привет! Мне удалось распараллелить это с помощью параллельной GNU, однако мне нужно подождать, чтобы убедиться, что мое решение работает правильно. В комментарии к предлагаемому решению - ну, собственно, поэтому мне и нужен GNU Parallel - в противном случае рабочие хосты будут забиты задачами и не смогут завершить работу. Представьте, что файл hosts имеет больше 4-8 записей, но путь содержит 10-20 тысяч путей. Что касается `nice` - без аргументов он меняет милость с 0 на 10 :) Johnny_Bit 7 лет назад 0
Я искал справочную страницу для хорошего http://man7.org/linux/man-pages/man1/nice.1.html Argonauts 7 лет назад 0
Опубликуйте ваше решение, используя параллельное, если можете, чтобы, если кто-то еще ищет это, он нашел его Argonauts 7 лет назад 0

Похожие вопросы