Przekaż wiele komend do stada

12
flock -x -w 5 ~/counter.txt 'COUNTER=$(cat ~/counter.txt); echo $((COUNTER + 1)) > ~/counter.txt'

Jak mam przekazać wiele poleceń, flockjak w powyższym przykładzie?

O ile rozumiem, flockbierze różne flagi (-x dla wyłączności, -w dla limitu czasu), następnie plik do zablokowania, a następnie polecenie do uruchomienia. Nie jestem pewien, w jaki sposób przekazałbym dwa polecenia do tej funkcji (ustaw zmienną z zawartością zablokowanego pliku, a następnie zwiększ ten plik).

Moim celem tutaj jest utworzenie nieco atomowego przyrostu dla pliku poprzez zablokowanie go za każdym razem, gdy skrypt próbuje uzyskać dostęp do counter.txtpliku.

d -_- b
źródło

Odpowiedzi:

8

Wywołaj jawnie powłokę.

flock -x -w 5 ~/counter.txt sh -c 'COUNTER=$(cat counter.txt); echo $((COUNTER + 1)) > ~/counter.txt'

Zauważ, że każda zmienna, którą zmieniasz, jest lokalna dla tego wystąpienia powłoki. Na przykład COUNTERzmienna nie zostanie zaktualizowana w skrypcie wywołującym: musisz ją odczytać z pliku (ale w międzyczasie mogła ulec zmianie) lub jako wynik polecenia:

new_counter=$(flock -x -w 5 ~/counter.txt sh -c 'COUNTER=$(cat counter.txt); echo $((COUNTER + 1)) | tee ~/counter.txt')
Gilles „SO- przestań być zły”
źródło
super, wielkie dzięki! Wyjaśnienie, które podałeś, zdecydowanie uratowało mnie od kolejnej godziny bólów głowy
d -_- b
4

Lub możesz zablokować deskryptor pliku

exec {counterfd}<~/counter.txt
flock -x -w 5 "$counterfd"
COUNTER=$(cat ~/counter.txt)
COUNTER=$(( COUNTER +1 ))
echo "$COUNTER" >~/counter.txt
exec {counterfd}<&-

Ma to również tę zaletę, że umożliwia bezpośrednie użycie zmiennej licznika, w przeciwieństwie do metod opartych na podpowłoce.

Richard Maw
źródło
Czy mógłbyś wyjaśnić exec {counterfd}? Sam w sobie Debian popełnia błędy not found, ale zwraca 0 z przekierowaniem. Bardzo dziwne.
Steve Almond
2

flockNarzędzie jest trochę trudne w użyciu, a strona man jest dość krótki. Strona podręcznika udostępnia trzy sposoby korzystania z tego narzędzia:

  • flock [options] <file|directory> <command> [command args]
  • flock [options] <file|directory> -c <command>
  • flock [options] <file descriptor number>

Sposób, w jaki sformułowane jest to pytanie, zdecydowanie użyłbym trzeciej formy flock. Jeśli przejdziesz dalej na stronę podręcznika, flockistnieje kilka przykładów, które pokazują dokładną składnię dla użycia trzeciego formularza:

#!/bin/bash
(
 flock -n 9 || exit 1
 echo "commands executed under lock..."
 echo "go here..."
) 9>/tmp/mylockfile

Dodałem #!/bin/bash.

Z powodzeniem wykorzystałem tę formę flock.

Trevor Boyd Smith
źródło