2008-11-28 11 views
9

C'est l'approche standard pour créer des verrous à l'aide du système de fichiers. Par exemple, visudo utilise:condition de course dans le verrou commun sur le fichier?

[ -f ".lock" ] && exit 1 
touch .lock 
# do something 
rm .lock 

1) Je suis confus, car il y a une condition de course, encore Linux utilise ce

2) est-il une meilleure façon de verrouiller les fichiers de shell?

3) ou dois-je utiliser des répertoires à la place?

Solution trouvée: man lockfile.

+1

Les questions doivent être marquées "[résolu]" en sélectionnant une réponse, et non en éditant le titre et en ajoutant "[résolu]". –

+0

problème est, je ne peux pas marquer ma propre réponse comme "accepté" –

+2

Je ne pense pas que votre réponse est la meilleure, franchement :) –

Répondre

17

Oui, il existe effectivement une condition de concurrence dans l'exemple de script. Vous pouvez utiliser l'option noclobber de bash pour obtenir un échec en cas de course, lorsqu'un script différent se faufile entre le test et le toucher.

Il est décrit here. J'ai extrait la pièce critique, avec quelques annotations (préfixé par BK :):

Une solution possible est d'utiliser la redirection IO et le mode noclobber de bash, qui ne sera pas rediriger vers un fichier existant . Nous pouvons utiliser quelque chose de similaire à:

if (set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; 
then 
    # BK: this will cause the lock file to be deleted in case of other exit 
    trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT 

    # critical-section BK: (the protected bit) 

    rm -f "$lockfile" 
    trap - INT TERM EXIT 
else 
    echo "Failed to acquire lockfile: $lockfile." 
    echo "Held by $(cat $lockfile)" 
fi 
+0

noclobber est utile, merci –

+1

Merci! [Repose ici] (http://stackoverflow.com/a/31955862/471376). – JamesThomasMoon1979

0

semble que j'ai trouvé une solution plus facile: l'homme lockfile

+1

Notez que lockfile n'est pas portable - il peut ne pas être disponible; cela fait partie de procmail (AFAIK). –

+0

Shell Linux encore moins :) –

+0

Le shell est plus portable que procmail, dans la mesure où vous êtes plus susceptible d'avoir bash que procmail. J'ai essayé Solaris, Linux, Mac et Windows ici. 'lockfile' n'est sur aucun d'entre eux. –

8

Essayez commande troupeau:

exec 200>"$LOCK_FILE" 
flock -e -n 200 || exit 1 

Il quittera si le fichier de verrouillage est verrouillé. Il est atomique et il fonctionnera sur la version récente de NFS.

J'ai fait un test. J'ai créé un fichier de compteur avec 0 dans et exécuté ce qui suit dans une boucle sur deux serveurs simultanément 500 fois:

#!/bin/bash 

exec 200>/nfs/mount/testlock 
flock -e 200 

NO=`cat /nfs/mount/counter` 
echo "$NO" 
let NO=NO+1 
echo "$NO" > /nfs/mount/counter 

Un nœud se battait avec l'autre pour la serrure. Quand les deux passages ont fini, le contenu du fichier était 1000. J'ai essayé plusieurs fois et ça marche toujours!

Remarque: Le client NFS est RHEL 5.2 et le serveur utilisé est NetApp.

+0

super article! merci – Janning

+0

Raisonnablement bonne couverture sur flock: dans mon échantillonnage, je l'ai sur Cygwin et Linux, mais pas Solaris ou Mac. –

+1

Pourriez-vous expliquer la syntaxe un peu plus? Je m'interroge particulièrement sur 'exec 200>" $ LOCK_FILE "'. Je vais le comprendre avec les pages man, mais votre réponse serait bien meilleure si elle expliquait ce que font ces lignes. –

Questions connexes