1

Я пытался распараллелить сценарий, который я использую, но пока что 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 ${hosts[$hostnum]} -i /root/.ssh/id_rsa "$DOMBAC - ${line[0]}" > "/data/backup/$DDAY/${line[1]}_${DATA}_FULL.tgz"

  let processed+=1;
done < paths

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

2 ответа2

1

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

cat paths | parallel --colsep ' ' echo {2} == {1}

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

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

cat paths | parallel --colsep ' ' -S server echo {2} == {1}

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

cat paths | parallel --colsep ' ' -j4 -S server echo {2} == {1}

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

cat paths | parallel --return {2} --cleanup --colsep ' ' -j4 -S server echo {2} == {1} '>' {2}

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

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

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

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

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

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

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

parallel --slf hosts.txt --ssh "ssh -i $HOME/.ssh/id_rsa.pub -lroot" --return /data/backup/$DDAY/./{2}_${DATA}_FULL.tgz --cleanup --colsep ' ' -j4 "$DOMBAC - {1} > {2}_${DATA}_FULL.tgz"
0

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

Чтобы выполнить это с минимальными изменениями в существующем скрипте, все, что нам нужно сделать, - это выполнить фон каждой задачи во время ее выполнения (для этого используется оператор &). Чтобы предотвратить потерянные процессы, мы должны убедиться, что скрипт не завершится, пока все задания не будут завершены, что выполняется с помощью встроенного wait bash. Команда 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 ${hosts[$hostnum]} -i /root/.ssh/id_rsa "$DOMBAC - ${line[0]}" > "/data/backup/$DDAY/${line[1]}_${DATA}_FULL.tgz" &

  let processed+=1;
done < paths
jobs
wait

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .