Какие команды Unix можно использовать как семафор / блокировку?
34
Я хочу запустить несколько сценариев оболочки Bash параллельно. Однако я хочу избежать гоночных условий. Какие команды Unix действительно атомарные, которые я мог бы использовать для этой цели, и как я могу их использовать?
Что вы делаете, что требует параллельной работы? Разве вы не можете выразить зависимости таким образом, чтобы параллель make(1)взяла верх? (т.е. make -j 9если у вас 8 ядер)? Это дает дополнительное преимущество чередования работы с более тонкой детализацией.
Если lockfileон не установлен в вашей системе, он mkdirвыполнит эту работу: это атомарная операция, и она завершится неудачно, если каталог уже существует (если вы не добавили параметр -pкомандной строки).
#!/bin/bash# Makes sure we exit if flock fails.set-e(# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10200# Do stuff)200>/var/lock/.myscript.exclusivelock
Это гарантирует, что код между "(" и ")" запускается только одним процессом за раз и что процесс слишком долго ожидает блокировки.
Хороший, не знал об этом. Тем не менее, это, по-видимому, специфично для Linux ...
Риккардо Мурри
1
@Riccardo, FreeBSD имеет аналогичную команду: lockf(1).
Алекс Б
lockf(1)не работает так, как в этом примере. Он не может принять номер дескриптора файла в качестве аргумента.
Чарли
11
lockfile (1) выглядит хорошим кандидатом, хотя имейте в виду, что это часть пакета procmail , который вы, возможно, еще не установили на своем компьютере. Это достаточно популярный пакет, который должен быть упакован для вашей системы, если он еще не установлен. Три из четырех систем, которые я проверил, имеют их, а другая - доступна.
Используя это просто:
#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`
echo Waitingfor lock $LOCKFILE...if lockfile -1-r15 $LOCKFILE
then# Do protected stuff here
echo Doing protected stuff...# Then, afterward, clean up so another instance of this script can run
rm -f $LOCKFILE
else
echo "Failed to acquire lock! lockfile(1) returned $?"
exit 1fi
Опции, которые я дал, повторяют попытку каждые 15 секунд. Сбросьте флаг "-r", если хотите, чтобы он ждал вечно.
Помните, что (в соответствии с man-страницей): «Как только файл заблокирован, к блокировке нужно прикасаться не реже одного раза в пять минут, иначе блокировка будет считаться устаревшей, и последующие попытки блокировки будут успешными».
Джей
6
Системный вызов mkdir()является атомарным в файловых системах POSIX. Таким образом, использование mkdirкоманды таким образом, чтобы она включала ровно один вызов mkdir(), достигло бы вашей цели. (IOW, не используйте mkdir -p). Соответствующая разблокировка rmdirконечно.
Предостережение: mkdir()не может быть атомарным в сетевых файловых системах.
Если вы работаете только в Unix, используйте fifos. Вы можете записывать рабочие записи в fifo и читать процессы из этого файла, и ваши читатели будут блокировать данные на fifo.
Блокировка файлов в порядке, но для того, что вы описываете, я бы пошел с fifos
make(1)
взяла верх? (т.е.make -j 9
если у вас 8 ядер)? Это дает дополнительное преимущество чередования работы с более тонкой детализацией.Ответы:
Если
lockfile
он не установлен в вашей системе, онmkdir
выполнит эту работу: это атомарная операция, и она завершится неудачно, если каталог уже существует (если вы не добавили параметр-p
командной строки).источник
flock(1)
Это гарантирует, что код между "(" и ")" запускается только одним процессом за раз и что процесс слишком долго ожидает блокировки.
источник
lockf(1)
.lockf(1)
не работает так, как в этом примере. Он не может принять номер дескриптора файла в качестве аргумента.lockfile (1) выглядит хорошим кандидатом, хотя имейте в виду, что это часть пакета procmail , который вы, возможно, еще не установили на своем компьютере. Это достаточно популярный пакет, который должен быть упакован для вашей системы, если он еще не установлен. Три из четырех систем, которые я проверил, имеют их, а другая - доступна.
Используя это просто:
Опции, которые я дал, повторяют попытку каждые 15 секунд. Сбросьте флаг "-r", если хотите, чтобы он ждал вечно.
источник
Системный вызов
mkdir()
является атомарным в файловых системах POSIX. Таким образом, использованиеmkdir
команды таким образом, чтобы она включала ровно один вызовmkdir()
, достигло бы вашей цели. (IOW, не используйтеmkdir -p
). Соответствующая разблокировкаrmdir
конечно.Предостережение:
mkdir()
не может быть атомарным в сетевых файловых системах.источник
rmdir
значит , и атомное?Возможно, команда lockfile сделает то, что вам нужно.
источник
Если вы работаете только в Unix, используйте fifos. Вы можете записывать рабочие записи в fifo и читать процессы из этого файла, и ваши читатели будут блокировать данные на fifo.
Блокировка файлов в порядке, но для того, что вы описываете, я бы пошел с fifos
источник
Как написано здесь: « Правильная блокировка в сценариях оболочки? », С использованием инструмента FLOM (Free LOck Manager) , сериализация команд и сценариев оболочки становится такой же простой, как запуск
FLOM позволяет вам реализовать более изощренные варианты использования (распределенная блокировка, считыватели / записи, числовые ресурсы и т. Д.), Как описано здесь: http://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/
источник