Многопоточность с помощью bash

#multithreading #bash #ssh

#многопоточность #bash #ssh

Вопрос:

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

сервер имеет следующую структуру каталогов:

 /usr/multi
    /1
        job
        file.a
        file.b
    /2
        job
        file.a
        file.b
    /3
        job
        file.a
        file.b
  

И следующий код:

 #this is thread.sh
cd /usr/multi
#find the first directory that has a job file    
id=$(ls */job)
#strip everything after "/" ("1/job" becomes "1")
id=${id%%/*}
#read job
read job <$id/job
if [ "$id" == "" ] || [ "$job" == "" ]
then
    false
else
    #mark that id as busy
    mv $id/job $id/_job
    #execute the job
    script.sh $1 $job
    #mark that id as available
    mv $id/_job $id/job
fi
  

script.sh выполняет некоторые операции (описанные в job файле и полученном аргументе) над file.a и file.b .

Клиенты, с другой стороны, выполняют этот код:

 #loop infinitely on failure, break loop on success
false
while [ "$?" != "0" ]
do
    result=$(ssh $server "thread.sh 'some instructions'" </dev/null)
done
echo $result
  

Таким образом , каждый клиент получает отдельный id и предоставляет серверу some instructions выполнить job указанное для этого id . Если на сервере больше клиентов, чем доступных заданий, клиенты будут продолжать пытаться захватить первое доступное id , и когда они это сделают, передайте some instructions серверу для выполнения соответствующего job .

Проблема в том, что время от времени два клиента получают одно и то же id ; и thread.sh путает file.a и file.b .

Моя теория заключается в том, что это происходит, когда два клиента запрашивают an id с сервера почти одновременно, поэтому сервер не может переименовать job файл достаточно быстро, чтобы один клиент увидел его как доступный, а другой — как занятый.

Должен ли я поставить случайный интервал ожидания непосредственно перед if [ "$id" == "" ] || [ "$job" == "" ] , чтобы я получил больше случайности во времени?

Комментарии:

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

Ответ №1:

Как вы правильно определили, ваш скрипт довольно колоритный.

Простая блокировка в bash может быть реализована с помощью

 set -o noclobber
  

и запись в файл блокировки. Если блокировка уже удерживается (файл существует), ваша попытка записи завершится неудачей атомарным образом.

Комментарии:

1. Итак, если я добавлю set -o noclobber в свой /etc/profile, я не позволю параллельно работающим cp и mv выполнять операции с одними и теми же файлами? Это так просто, или я что-то здесь упускаю?

2. Не делайте этого в profile , сделайте это в скрипте, который выполняет блокировку. Это не влияет cp или mv вообще. Это влияет на поведение перенаправления вывода через >filename . См. Руководство по Bash, gnu.org/software/bash/manual/bashref.html#Redirecting-Output

3. как насчет mv -n моего файла задания?

4. Чтобы избежать состояния гонки, вам нужен механизм блокировки. Изменение используемых вами команд вам не поможет, пока ваш параллелизм остается неконтролируемым.