Jakie polecenia uniksowe mogą być użyte jako semafor / blokada?
34
Chcę uruchomić wiele skryptów powłoki Bash równolegle. Chcę jednak uniknąć warunków wyścigowych. Jakie polecenia uniksowe są naprawdę atomowe, których mógłbym użyć do tego celu i jak ich używać?
Co robisz, że wymaga pracy równoległej? Czy nie potrafisz wyrazić zależności w sposób umożliwiający make(1)przejęcie równoległości ? (tj. zrobić, make -j 9jeśli masz 8 rdzeni)? Ma to dodatkową zaletę polegającą na przeplataniu z większą dokładnością.
Jeśli lockfilenie jest zainstalowany w systemie, mkdirwykona pracę: jest to operacja atomowa i kończy się niepowodzeniem, jeśli katalog już istnieje (o ile nie dodasz -pprzełącznika wiersza polecenia).
#!/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
Zapewnia to, że kod między „(” a „)” jest uruchamiany tylko przez jeden proces na raz i że proces zbyt długo czeka na blokadę.
Fajny, nie wiedziałem o tym. Jednak najwyraźniej jest specyficzny dla Linuksa ...
Riccardo Murri,
1
@Riccardo, FreeBSD ma podobną komendę: lockf(1).
Alex B,
lockf(1)nie działa jednak tak, jak w tym przykładzie. Nie może przyjmować numeru deskryptora pliku jako argumentu.
Charley,
11
lockfile (1) wygląda na dobrego kandydata, choć uważaj, że jest on częścią pakietu procmail , którego być może jeszcze nie zainstalowałeś na swoim komputerze. Jest to wystarczająco popularny pakiet, który powinien zostać spakowany dla twojego systemu, jeśli nie jest jeszcze zainstalowany. Trzy z czterech sprawdzonych systemów mają go, a drugi ma go dostępny.
Korzystanie z niego jest proste:
#!/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
Opcje, które podałem, sprawiają, że ponawia próbę co sekundę przez maksymalnie 15 sekund. Opuść flagę „-r”, jeśli chcesz czekać wiecznie.
Należy pamiętać, że (według strony podręcznika): „Gdy plik zostanie zablokowany, blokada musi być dotykana co najmniej raz na pięć minut, w przeciwnym razie blokada zostanie uznana za przestarzałą, a kolejne próby blokady zakończą się powodzeniem”.
Jay
6
Wywołanie systemowe mkdir()jest atomowe w systemach plików POSIX. Zatem użycie mkdirpolecenia w taki sposób, aby mkdir()wymagało dokładnie jednego połączenia, aby osiągnąć cel. (IOW, nie używaj mkdir -p). Odpowiednie odblokowanie jest rmdiroczywiście.
Zastrzeżenie emptor: mkdir()może nie być atomowy w sieciowych systemach plików.
make(1)
przejęcie równoległości ? (tj. zrobić,make -j 9
jeśli masz 8 rdzeni)? Ma to dodatkową zaletę polegającą na przeplataniu z większą dokładnością.Odpowiedzi:
Jeśli
lockfile
nie jest zainstalowany w systemie,mkdir
wykona pracę: jest to operacja atomowa i kończy się niepowodzeniem, jeśli katalog już istnieje (o ile nie dodasz-p
przełącznika wiersza polecenia).źródło
flock(1)
Zapewnia to, że kod między „(” a „)” jest uruchamiany tylko przez jeden proces na raz i że proces zbyt długo czeka na blokadę.
źródło
lockf(1)
.lockf(1)
nie działa jednak tak, jak w tym przykładzie. Nie może przyjmować numeru deskryptora pliku jako argumentu.lockfile (1) wygląda na dobrego kandydata, choć uważaj, że jest on częścią pakietu procmail , którego być może jeszcze nie zainstalowałeś na swoim komputerze. Jest to wystarczająco popularny pakiet, który powinien zostać spakowany dla twojego systemu, jeśli nie jest jeszcze zainstalowany. Trzy z czterech sprawdzonych systemów mają go, a drugi ma go dostępny.
Korzystanie z niego jest proste:
Opcje, które podałem, sprawiają, że ponawia próbę co sekundę przez maksymalnie 15 sekund. Opuść flagę „-r”, jeśli chcesz czekać wiecznie.
źródło
Wywołanie systemowe
mkdir()
jest atomowe w systemach plików POSIX. Zatem użyciemkdir
polecenia w taki sposób, abymkdir()
wymagało dokładnie jednego połączenia, aby osiągnąć cel. (IOW, nie używajmkdir -p
). Odpowiednie odblokowanie jestrmdir
oczywiście.Zastrzeżenie emptor:
mkdir()
może nie być atomowy w sieciowych systemach plików.źródło
rmdir
zatem również atomowy?Może polecenie lockfile zrobi to, czego potrzebujesz.
źródło
Jeśli używasz tylko Uniksa, użyj fifos. Możesz zapisać rekordy pracy do fifo i odczytać procesy z tego pliku, a twoi czytelnicy będą blokować na fifo.
Zablokuj pliki są w porządku, ale dla tego, co opisujesz, wybrałbym z fifos
źródło
Jak napisano tutaj: „ Prawidłowe blokowanie w skryptach powłoki? ”, Używając narzędzia FLOM (Free LOck Manager) , serializowanie poleceń i skryptów powłoki staje się tak proste, jak uruchamianie
FLOM pozwala na implementację bardziej skomplikowanych przypadków użycia (blokowanie rozproszone, czytniki / zapisy, zasoby numeryczne itp.), Jak wyjaśniono tutaj: http://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/
źródło