Il blocco consultivo è stato utilizzato per secoli e può essere utilizzato negli script bash. Preferisco il semplice flock
(da util-linux[-ng]
) su lockfile
(da procmail
). E ricorda sempre una trappola all'uscita (sigspec ==EXIT
o 0
, intercettare segnali specifici è superfluo) in quegli script.
Nel 2009 ho rilasciato il mio script lockable boilerplate (originariamente disponibile nella mia pagina wiki, oggi disponibile come Gist). Trasformarlo in un'istanza per utente è banale. Usandolo puoi anche scrivere facilmente script per altri scenari che richiedono un certo blocco o sincronizzazione.
Ecco il boilerplate menzionato per tua comodità.
#!/bin/bash
# SPDX-License-Identifier: MIT
## Copyright (C) 2009 Przemyslaw Pawelczyk <[email protected]>
##
## This script is licensed under the terms of the MIT license.
## https://opensource.org/licenses/MIT
#
# Lockable script boilerplate
### HEADER ###
LOCKFILE="/var/lock/`basename $0`"
LOCKFD=99
# PRIVATE
_lock() { flock -$1 $LOCKFD; }
_no_more_locking() { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking() { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }
# ON START
_prepare_locking
# PUBLIC
exlock_now() { _lock xn; } # obtain an exclusive lock immediately or fail
exlock() { _lock x; } # obtain an exclusive lock
shlock() { _lock s; } # obtain a shared lock
unlock() { _lock u; } # drop a lock
### BEGIN OF SCRIPT ###
# Simplest example is avoiding running multiple instances of script.
exlock_now || exit 1
# Remember! Lock file is removed when one of the scripts exits and it is
# the only script holding the lock or lock is not acquired at all.
Se lo script è lo stesso per tutti gli utenti, puoi utilizzare un lockfile
approccio. Se acquisisci il blocco, procedi altrimenti mostra un messaggio ed esci.
Ad esempio:
[Terminal #1] $ lockfile -r 0 /tmp/the.lock
[Terminal #1] $
[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] lockfile: Sorry, giving up on "/tmp/the.lock"
[Terminal #1] $ rm -f /tmp/the.lock
[Terminal #1] $
[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] $
Dopo /tmp/the.lock
è stato acquisito il tuo script sarà l'unico con accesso all'esecuzione. Quando hai finito, basta rimuovere il lucchetto. In forma di script potrebbe essere simile a:
#!/bin/bash
lockfile -r 0 /tmp/the.lock || exit 1
# Do stuff here
rm -f /tmp/the.lock
Penso flock
è probabilmente la variante più semplice (e memorabile). Lo uso in un cron job per codificare automaticamente dvd e cd
# try to run a command, but fail immediately if it's already running
flock -n /var/lock/myjob.lock my_bash_command
Usa -w
per i timeout o le opzioni di tralasciare attendere fino a quando il blocco non viene rilasciato. Infine, la pagina man mostra un bell'esempio per più comandi:
(
flock -n 9 || exit 1
# ... commands executed under lock ...
) 9>/var/lock/mylockfile