Удаленная очередь задач с использованием bash & ssh для переменного числа живых работников
Я хочу распределить работу с главного сервера на несколько рабочих серверов с помощью пакетов.
В идеале у меня был бы tasks.txt
файл со списком задач для выполнения
cmd args 1
cmd args 2
cmd args 3
cmd args 4
cmd args 5
cmd args 6
cmd args 7
...
cmd args n
и каждый рабочий сервер будет подключаться с помощью ssh, читать файл и отмечать каждую строку как в процессе или сделано
#cmd args 1 #worker1 - done
#cmd args 2 #worker2 - in progress
#cmd args 3 #worker3 - in progress
#cmd args 4 #worker1 - in progress
cmd args 5
cmd args 6
cmd args 7
...
cmd args n
Я знаю, как сделать ssh-соединение, прочитать файл и выполнить удаленно, но не знаю, как сделать чтение и запись атомной операции, в чтобы не было случаев, когда 2 сервера запускают одну и ту же задачу, и как обновить строку.
Я хотел бы, чтобы каждый работник переходил к списку задач и блокировал следующую доступную задачу в списке, а не сервер, активно командующий рабочими, поскольку у меня будет гибкое количество рабочих клонов, которые я начну или закрою в зависимости от того, как быстро мне понадобятся задачи для завершения.
обновление:
и моя ideea для рабочего скрипта будет :
#!/bin/bash
taskCmd=""
taskLine=0
masterSSH="ssh usr@masterhost"
tasksFile="/path/to/tasks.txt"
function getTask(){
while [[ $taskCmd == "" ]]
do
sleep 1;
taskCmd_and_taskLine=$($masterSSH "#read_and_lock_next_available_line $tasksFile;")
taskCmd=${taskCmd_and_taskLine[0]}
taskLine=${taskCmd_and_taskLine[1]}
done
}
function updateTask(){
message=
$masterSSH "#update_currentTask $tasksFile $taskLine $message;"
}
function doTask(){
return $taskCmd;
}
while [[ 1 -eq 1 ]]
do
getTask
updateTask "in progress"
doTask
taskErrCode=$?
if [[ $taskErrCode -eq 0 ]]
then
updateTask "done, finished successfully"
else
updateTask "done, error $taskErrCode"
fi
taskCmd="";
taskLine=0;
done
3 ответов
можно использовать flock
для одновременного доступа к файлу:
exec 200>>/some/any/file ## create a file descriptor
flock -w 30 200 ## concurrently access /some/any/file, timeout of 30 sec.
вы можете указать дескриптор файла в список задач или любой другой файл, но, конечно же, тот же файл, чтобы flock
работа. Замок я снял, как только что это сделал или плохо. Вы также можете удалить замок самостоятельно, когда он вам больше не нужен:
flock -u 200
пример использования:
ssh user@x.x.x.x '
set -e
exec 200>>f
echo locking...
flock -w 10 200
echo working...
sleep 5
'
set -e
сбой сценария при сбое любого шага. Играть с the sleep
time и выполнить этот скрипт параллельно. Только один sleep
будет выполняться одновременно.
попробуйте реализовать что-то вроде
while read line; do
echo $line
#check if the line contains the # char, if not execute the ssh, else nothing to do
checkAlreadyDone=$(grep "^#" $line)
if [ -z "${checkAlreadyDone}" ];then
<insert here the command to execute ssh call>
<here, if everything has been executed without issue, you should
add a commad to update the file taskList.txt
one option could be to insert a sed command but it should be tested>
else
echo "nothing to do for $line"
fi
done < taskList.txt
С уважением Клаудио!--2-->
Проверьте, изобретаете ли вы GNU Parallel:
parallel -S worker1 -S worker2 command ::: arg1 arg2 arg3
GNU Parallel является общим параллелизатором и позволяет легко запускать задания параллельно на одной машине или на нескольких машинах, к которым у вас есть доступ ssh. Он часто может заменить for
петли.
Если у вас есть 32 разных задания, которые вы хотите запустить на 4 процессорах, прямой способ распараллеливания-запустить 8 заданий на каждом процессоре:
GNU Parallel вместо этого порождает новый процесс когда один заканчивает-сохраняя процессоры активными и, таким образом, экономя время:
установка
Если GNU Parallel не упакован для вашего дистрибутива, вы можете выполнить личную установку, которая не требует корневого доступа. Это можно сделать за 10 секунд, сделав следующее:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
для других вариантов установки см. http://git.savannah.gnu.org/cgit/parallel.git/tree/README
узнать больше
см. дополнительные примеры:http://www.gnu.org/software/parallel/man.html
смотрите вступление видео:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
пройдите через учебник:http://www.gnu.org/software/parallel/parallel_tutorial.html
подпишитесь на список электронной почты, чтобы получить поддержку:https://lists.gnu.org/mailman/listinfo/parallel