Obtenez un verrou de lecture / écriture exclusif sur un fichier pour les mises à jour atomiques

10

Je veux avoir un fichier utilisé comme compteur. L'utilisateur A écrit et incrémente ce nombre, tandis que l'utilisateur B demande de lire le fichier. Est-il possible que l'utilisateur A puisse verrouiller ce fichier afin que personne ne puisse y lire ou y écrire tant que l'écriture de l'utilisateur A n'est pas terminée?

J'ai regardé flockmais je n'arrive pas à le faire fonctionner comme je m'y attendais.

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

S'il existe un moyen plus approprié d'obtenir ce fichier d'incrémentation de type atomique, ce serait génial d'entendre aussi!

Mon but est:

LOCK counter.txt; write to counter.txt;

pendant ce temps-là

Read counter.txt; realize it's locked so wait until that lock is finished.
d -_- b
la source
1
"Je n'arrive pas à le faire fonctionner comme je l'attends." Qu'est -ce que cela signifie concrètement ?
John1024
Je suis sûr que je ne l'utilise pas correctement, mais en utilisant le code ci-dessus, je peux utiliser deux shells et les faire éditer tous les deux le fichier de compteur pendant que je pensais que l'un le verrouillait. Donc, si je lance cette ligne deux fois sur deux shells distincts, (chacun avec son propre numéro à faire écho), je vois toujours le deuxième numéro en cours d'écriture
d -_- b
1
Lorsque le premier termine et libère son verrou, le second s'exécute. N'est-ce pas ainsi que cela devrait fonctionner? (Dans le code ci-dessus, && sleep 5est exécuté après que le troupeau a
libéré
Hmm intéressant ... Donc, dans ce cas, il aurait été trop rapide pour mon œil humain d'attraper. Génial! Mon prochain défi est de savoir comment mettre plusieurs commandes flock, mais je vais poser cela comme une question distincte. Merci John!
d -_- b
3
@d -_- b J'adore votre nom d'utilisateur. C'est le nom d'utilisateur LE PLUS intelligent que j'aie jamais vu.
Devyn Collier Johnson

Réponses:

10

Le traitement par Bash de la commande ci-dessous peut être surprenant:

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

Bash s'exécute d'abord flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txtet, si cela se termine avec succès (libération du verrou), il s'exécute sleep 5. Ainsi, le verrou n'est pas maintenu pendant les 5 secondes que l'on peut attendre.

Mis à part &contre&&

Si l'on a deux commandes, Aet Balors:

  1. A & Bdémarre Aen arrière-plan puis démarre Bsans attendre la Afin.

  2. A && Bdémarre A, attend qu'il se termine, puis, s'il se termine avec succès (code de sortie 0), démarre B. Si Aéchoue (code de sortie différent de zéro), il Bn'est jamais exécuté.

En somme, &et ce &&sont deux opérateurs de liste complètement différents.

John1024
la source
3
il me surprendre si A && B, Aattendrait Bà la fin.
Andras Gyomrey
1
dans A && B, A est exécuté en premier. B n'est exécuté que si A s'est exécuté et s'est terminé avec succès. Utiliser un; B pour toujours exécuter B quel que soit le statut d'exécution de A.
kapad
15

Les verrous de fichiers ne sont pas obligatoires 1 - c'est-à-dire que vous ne pouvez pas verrouiller un fichier de sorte qu'un autre processus ne puisse pas y accéder. Le verrouillage d'un fichier signifie que si un (autre) processus vérifie s'il a été verrouillé, il le saura.

Le but de flockest de faire des choses comme ce que vous voulez, mais vous devez ensuite les utiliser flockpour chaque tentative d'accès . Gardez à l'esprit que ces appels bloquent; de man flock:

si le verrou ne peut pas être acquis immédiatement, le troupeau attend que le verrou soit disponible


1. Ce qui rend la fonctionnalité inutile si vous l'utilisez pour, par exemple, la sécurité, mais ce n'est pas le but des verrous de fichiers - ils sont pour la synchronisation, c'est ce que vous faites. L'utilisateur Leo a souligné qu'il peut y avoir une implémentation non standardisée du verrouillage de fichiers obligatoire dans le noyau Linux ( voir cette discussion ), basée sur des parallèles historiques d'autres systèmes d'exploitation * nix. Cependant, cela semble être une interface de niveau C uniquement.

boucle d'or
la source
Merci! Cela aide à donner un sens à l'aspect «consultatif» et à la façon dont je dois l'utiliser à flockchaque fois. très utile!
d -_- b
2

Vous pouvez utiliser "commande sh -c ..." pour exécuter la commande shell entière, y compris la redirection de fichiers, avec le verrou maintenu. De plus, comme vous utilisez le fichier comme compteur, vous devez maintenir le verrou en continu pendant que vous effectuez la lecture et la réécriture. Donc, vous voudriez faire quelque chose comme ça pour incrémenter le compteur et retourner sa nouvelle valeur:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count + 1)) > /dev/shm/counter.txt ; echo $((count + 1))'

Changer les signes plus en signes moins devrait décrémenter le compteur:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count - 1)) > /dev/shm/counter.txt ; echo $((count - 1))'

Je m'attends à ce que vous initialisiez le compteur avant que tout conflit ne se produise, il ne devrait donc pas être nécessaire de vous soucier du verrouillage aussi tôt:

echo 0 > /dev/shm/counter.txt

Je ne pense pas que vous auriez jamais besoin d'altérer la valeur du compteur alors que des conflits pourraient se produire, mais, si vous l'avez déjà fait, vous devriez le faire de la manière suivante:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'echo 0 > /dev/shm/counter.txt'

Je pense que vous comprenez comment faire la lecture, mais je l'inclus pour être complet:

flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt
Adam Richter
la source
Cela semble être la seule réponse qui remarque correctement que dans la question, le fichier est ouvert par le shell avant même que le troupeau ne s'exécute ...
Eichin