Wykonywanie operacji zapisu atomowego w pliku bash


13

Po przejrzeniu dokumentacji bash , to pytanie i to wciąż nie jest dla mnie jasne, w jaki sposób mogę wykonać operacje zapisu atomowego (dołączyć) do pliku w bash. Mam skrypt uruchamiany w wielu instancjach, który w pewnym momencie musi zapisać dane do pliku:

echo "$RESULT" >> `pwd`/$TEMP_DIR/$OUT_FILE

Jak to możliwe, aby wszystkie operacje zapisu ze wszystkich jednocześnie działających skryptów do tego pliku były atomowe (aby dane z jednej instancji nie nakładały się na dane z innej)?


1
Do twojej wiadomości nie potrzebujesz `pwd`; możesz po prostu użyć kropki ( .). Powinieneś także zacytować całą nazwę pliku, ponieważ zawiera on zmienne .
— Wildcard,

1
Możesz także rozważyć możliwość korzystania z FIFO .
— Wildcard,

@Wildcard Thanks. Użyłem pwdwcześniej w skrypcie, aby powiadomić użytkownika o bieżącym katalogu roboczym, a także zapisywać wpisy w pliku dziennika. patrząc teraz na FIFO.
— Sebi,

1
Właściwie na tej stronie jest lepsze wprowadzenie do FIFO ; link, który podałem kilka minut temu, jest specyfikacją POSIX mkfifoi nie jest dokładnie poziomem wprowadzającym.
— Wildcard,

Niezależnie od tego, czy jest to plik FIFO, czy plik, nadal istnieje ryzyko, że dwie instancje będą zapisywać w tym samym czasie i nawzajem wymieszać dane wyjściowe.
— clacke

Odpowiedzi:


10

Wydaje się, że musisz użyć flockjak w przykładzie z man ( http://linux.die.net/man/1/flock )

(
flock -x 200

# Put here your commands that must do some writes atomically

) 200>/var/lock/mylockfile 

I umieść wszystkie swoje polecenia, które muszą być atomowe w ().


Operacja zapisu będzie miała charakter atomowy, mimo że (flock -s 200 # Umieścić tutaj swoje polecenia, które muszą wykonywać niektóre zapisy atomowe) 200> / var / lock / mylockfile działa w wielu równolegle działających skryptach? Lub odwrotnie, czy blokada dotyczy tylko / var / lock / mylockfile?
— Sebi,

1
Twój skrypt blokuje / var / lock / mylockfile, ale tylko jedna instancja skryptu może uzyskać na nim blokadę zapisu. Inne instancje będą czekać, aż /var/lock/mylockfilebędzie dostępna blokada.

-s jest blokadą współdzieloną - odpowiednią do odczytu, do blokady zapisu należy użyć opcji -x / -e. Znajduje się on na stronie podręcznika, do której linkowałeś.
— Evan Benn,

W którym momencie następuje odblokowanie w tym kodzie? Jak tylko coś zostanie zapisane /var/lock/mylockfilew procesie, który zadzwonił flock -x?
— Chris Stryczyński

@ChrisStryczynski Możesz uruchomić ten przykład (flock -x 200; date; sleep 10; date;) 200>/var/lock/mylockfilew dwóch powłokach i zobaczyć, że odblokowanie nastąpi dopiero po wykonaniu wszystkich poleceń in () (czyli w podpowłoce)

4

flockjest jednym ze sposobów blokowania operacji. Narzędzie to jest częścią zestawu narzędzi util-linux i jest dostępne tylko dla systemu Linux. Inne narzędzia, dostępne na szerokiej gamie platform, są oparte na setlockużyteczności Daniela J. Bernsteina z jego pakietu daemontools:

Narzędzia te działają z nieco innym paradygmatem niż ten zastosowany w odpowiedzi M. Kurenkowa (taki, który flockmoże również zastosować, ale nie ma w tej odpowiedzi). Wywołuje się setlockprogram, aby powiązać obciążenie z poleceniem, które musi być zablokowane. setlocksam się otwiera i blokuje plik blokady i pozostawia deskryptor pliku dla niego otwarty w trakcie procesu. Blokada trwa tak długo, jak trwa ten proces (chyba że kolejne polecenie powiązane w celu jawnego zwolnienia blokady przez znalezienie i zamknięcie deskryptora otwartego pliku).

W tym przypadku należy zablokować polecenie, które tworzy linię wyjściową, mając świadomość, że wywołuje to polecenie zewnętrzne echo zamiast wbudowanego echopolecenia powłoki :

echo pliku blokującego setlock „$ RESULT” >> ./$TEMP_DIR/$OUT_FILE

W takim przypadku nie jest konieczne blokowanie otwierania pliku wyjściowego w trybie dołączania. Gdyby tak było, należałoby otworzyć ten plik w zamku, co wymaga użycia programów takich jak fdredir/ redirfd:

setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" echo "$ RESULT"
który można zmienić w funkcję powłoki, jeśli chce się:

outfile () {setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" "$ @"; } 
[…]
Echo wyjściowe „$ RESULT”
lub trzymanie się składni powłoki i interpretowanie jej przez drugą powłokę działającą pod blokadą, wymagającą nietrywialnego cytowania, jeśli zmienne powłoki nie są eksportowane jako zmienne środowiskowe:

setlock mylockfile sh -c 'echo' "$ RESULT" '>> "./'$TEMP_DIR'/'$OUT_FILE'"

To oczywiście uogólnia na rzeczy inne niż pisanie do plików wyjściowych:

setlock mylockfile sh -c '… zablokowane; rzeczy…

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.