#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-Output3. как насчет
mv -n
моего файла задания?4. Чтобы избежать состояния гонки, вам нужен механизм блокировки. Изменение используемых вами команд вам не поможет, пока ваш параллелизм остается неконтролируемым.