Le verrouillage consultatif est utilisé depuis des lustres et peut être utilisé dans les scripts bash. Je préfère le flock
simple (à partir de util-linux[-ng]
) sur lockfile
(à partir de procmail
). Et rappelez-vous toujours d'un piège à la sortie (sigspec ==EXIT
ou 0
, le piégeage de signaux spécifiques est superflu) dans ces scripts.
En 2009, j'ai publié mon passe-partout de script verrouillable (disponible à l'origine sur ma page wiki, aujourd'hui disponible sous forme d'essentiel). Transformer cela en une instance par utilisateur est trivial. En l'utilisant, vous pouvez également facilement écrire des scripts pour d'autres scénarios nécessitant un verrouillage ou une synchronisation.
Voici le passe-partout mentionné pour votre commodité.
#!/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.
Si le script est le même pour tous les utilisateurs, vous pouvez utiliser un lockfile
approcher. Si vous acquérez le verrou, continuez, sinon affichez un message et quittez.
Par exemple :
[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] $
Après /tmp/the.lock
a été acquis votre script sera le seul à avoir accès à l'exécution. Lorsque vous avez terminé, retirez simplement le verrou. Sous forme de script, cela pourrait ressembler à :
#!/bin/bash
lockfile -r 0 /tmp/the.lock || exit 1
# Do stuff here
rm -f /tmp/the.lock
Je pense flock
est probablement la variante la plus facile (et la plus mémorable). Je l'utilise dans une tâche cron pour encoder automatiquement des DVD et des CD
# try to run a command, but fail immediately if it's already running
flock -n /var/lock/myjob.lock my_bash_command
Utilisez -w
pour les délais d'attente ou laissez les options d'attente jusqu'à ce que le verrou soit libéré. Enfin, la page de manuel montre un bel exemple pour plusieurs commandes :
(
flock -n 9 || exit 1
# ... commands executed under lock ...
) 9>/var/lock/mylockfile