Je veux exécuter plusieurs scripts de shell bash en parallèle. Cependant, je veux éviter les conditions de race. Quelles commandes UNIX sont Vraiment atomique que je pourrais utiliser à cette fin et comment puis-je les utiliser?
Si lockfile
_ n'est pas installé sur votre système, alors mkdir
_ _ _ _ va faire le travail: c'est une opération atomique, et elle échoue si le répertoire existe déjà (tant que vous n'ajoutez pas de -p
Commutateur de commande).
create_lock_or_wait () {
path="$1"
wait_time="${2:-10}"
while true; do
if mkdir "${path}.lock.d"; then
break;
fi
sleep $wait_time
done
}
remove_lock () {
path="$1"
rmdir "${path}.lock.d"
}
#!/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 10 200
# Do stuff
) 200>/var/lock/.myscript.exclusivelock
Cela garantit que le code entre "(" et ")" ne fonctionne que par un processus à la fois et que le processus attendra une serrure trop longue.
lockfile (1) ressemble à un bon candidat, mais attention à ce que cela fait partie du package PROCMAIL , que vous n'avez peut-être pas encore installé sur votre appareil. C'est un paquet assez populaire qu'il devrait être emballé pour votre système s'il n'est pas encore installé. Trois des quatre systèmes que j'ai vérifié l'ont, et l'autre l'a disponible.
En utilisant c'est simple:
#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`
echo Waiting for 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 1
fi
Les options que j'ai données pour réessayer une fois une seconde pendant 15 secondes maximum. Déposez le drapeau "-r" si vous voulez attendre pour toujours.
L'appel système mkdir()
est atomique sur les systèmes de fichiers POSIX. Ainsi, à l'aide de la commande mkdir
_ de telle manière que cela implique exactement un appel à mkdir()
obtiendrait votre objectif. (Iow, n'utilisez pas mkdir -p
). Le déverrouillage correspondant est rmdir
bien sûr.
Cavalier vide: mkdir()
peut ne pas être atomique sur les systèmes de fichiers réseau.
Peut-être que la commande Lockfile fera ce dont vous avez besoin.
lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock
Si vous ne courez que sur UNIX, utilisez des FIFOs. Vous pouvez écrire des enregistrements de travail à la FIFO et avoir des processus lire à partir de ce fichier et vos lecteurs bloqueront sur les FIFO.
Les fichiers de verrouillage sont ok, mais pour ce que vous décrivez, j'irais avec des FIFOs