Как мне синхронизировать (блокировать / разблокировать) доступ к файлу в bash из нескольких скриптов? - PullRequest
19 голосов
/ 23 февраля 2010

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

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

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

Другим решением является установка блокировки процесса вместо записи файла, что означает, что первый скрипт для доступа к входному файлу запустит процесс с именем lock_input, а другие скрипты ps -elf | grep lock_input. Если он присутствует в списке процессов, они будут ждать. Это может быть быстрее, чем запись в NFS, но все же не идеальное решение ...

Итак, мой вопрос : существует ли какая-либо команда bash (или другой интерпретатор сценариев) или служба, которую я могу использовать, которая будет вести себя как блокировки семафора или мьютекса, используемые для синхронизации в программировании потоков?

Спасибо.

Небольшой пример:

Допустим, у нас есть input_file следующим образом:

Monday
Tuesday
Wednesday
Thursday
Friday
Saturday 
Sunday

Сценарий обработки: TrScript.sh

#!/bin/bash  
NbLines=$(cat input_file | wc -l)  
while [ ! $NbLines = 0 ]  
do  
  FirstLine=$(head -1 input_file)  
  echo "Hello World today is $FirstLine"  
  RemainingLines=$(expr $NbLines - 1 )  
  tail -n $RemainingLines input_file > tmp  
  mv tmp input_file  
  NbLines=$(cat input_file | wc -l)   
done

Основной скрипт:

#! /bin/bash  
./TrScript.sh &  
./TrScript.sh &  
./TrScript.sh &  
wait

Результат должен быть:

Hello World today is Monday  
Hello World today is Tuesday  
Hello World today is Wednesday  
Hello World today is Thursday  
Hello World today is Friday  
Hello World today is Saturday  
Hello World today is Sunday

Ответы [ 3 ]

15 голосов
/ 24 февраля 2010

использование

line=`flock $lockfile -c "(gawk 'NR==1' < $infile ; gawk 'NR>1' < $infile > $infile.tmp ; mv $infile.tmp $infile)"`

для доступа к файлу, из которого вы хотите прочитать. При этом используются блокировки файлов.

gawk NR==1 < ...

печатает первую строку ввода

10 голосов
/ 23 февраля 2010

Мне всегда нравилась программа lockfile (пример поиска для lockfile manpage ) из набора инструментов procmail (должен быть доступным в большинстве систем, хотя он может быть не установлен по умолчанию).

Он был разработан для блокировки почтовых файлов, которые (были?) Обычно монтируются через NFS, поэтому он работает должным образом по NFS (как и все, что может).

Кроме того, если вы делаете предположение, что все ваши «работники» находятся на одном компьютере (предполагая, что вы можете проверять PID, которые могут не работать должным образом, когда PID в конечном итоге переносятся), вы можете поставить свою блокировку файл в каком-либо другом локальном каталоге (например, / tmp) при обработке файлов, размещенных на сервере NFS. Пока все работники используют одно и то же расположение файла блокировки (и однозначное сопоставление имен файлов блокировки с заблокированными путями), оно будет работать нормально.

1 голос
/ 25 апреля 2014

Использование FLOM (Free LOck Manager) инструмент вашего основного скрипта может стать таким простым:

#!/bin/bash  
flom -- ./TrScript.sh &  
flom -- ./TrScript.sh &  
flom -- ./TrScript.sh &  
wait

, если вы запускаете скрипт внутри одного хоста и что-то вроде:

flom -A 224.0.0.1 -- ./TrScript.sh &

, если вы хотите распространить свой скрипт на множество хостов.Некоторые примеры использования доступны по этому адресу: http://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/

...