Passer plusieurs commandes pour affluer

12
flock -x -w 5 ~/counter.txt 'COUNTER=$(cat ~/counter.txt); echo $((COUNTER + 1)) > ~/counter.txt'

Comment passer plusieurs commandes flockcomme dans l'exemple ci-dessus?

Pour autant que je comprends, flockprend différents drapeaux (-x pour exclusif, -w pour timeout), puis le fichier à verrouiller, puis la commande à exécuter. Je ne sais pas comment je passerais deux commandes dans cette fonction (définir une variable avec le contenu du fichier verrouillé, puis incrémenter ce fichier).

Mon objectif ici est de créer un incrément quelque peu atomique pour un fichier en le verrouillant chaque fois qu'un script essaie d'accéder au counter.txtfichier.

d -_- b
la source

Réponses:

8

Appelez explicitement un shell.

flock -x -w 5 ~/counter.txt sh -c 'COUNTER=$(cat counter.txt); echo $((COUNTER + 1)) > ~/counter.txt'

Notez que toute variable que vous modifiez est locale à cette instance de shell. Par exemple, la COUNTERvariable ne sera pas mise à jour dans le script appelant: vous devrez la relire à partir du fichier (mais elle peut avoir changé entre-temps), ou en sortie de la commande:

new_counter=$(flock -x -w 5 ~/counter.txt sh -c 'COUNTER=$(cat counter.txt); echo $((COUNTER + 1)) | tee ~/counter.txt')
Gilles 'SO- arrête d'être méchant'
la source
génial, merci beaucoup! L'explication que vous avez fournie m'a certainement sauvé d'une autre heure de maux de tête
d -_- b
4

Ou vous pouvez regrouper un descripteur de fichier

exec {counterfd}<~/counter.txt
flock -x -w 5 "$counterfd"
COUNTER=$(cat ~/counter.txt)
COUNTER=$(( COUNTER +1 ))
echo "$COUNTER" >~/counter.txt
exec {counterfd}<&-

Cela a également l'avantage de vous permettre d'utiliser directement la variable de compteur, contrairement aux approches basées sur les sous-shells.

Richard Maw
la source
Pourriez-vous expliquer cela exec {counterfd}? À lui seul, des erreurs Debian not found, mais il retourne 0 avec la redirection. Très étrange.
Steve Almond
2

L' flockoutil est un peu délicat à utiliser et la page de manuel est assez courte. La page de manuel propose trois façons d'utiliser l'outil:

  • flock [options] <file|directory> <command> [command args]
  • flock [options] <file|directory> -c <command>
  • flock [options] <file descriptor number>

La façon dont cette question est formulée, j'utiliserais certainement la troisième forme de flock. Si vous allez plus loin dans la page de manuel, flockil y a quelques exemples qui montrent la syntaxe exacte pour utiliser le troisième formulaire:

#!/bin/bash
(
 flock -n 9 || exit 1
 echo "commands executed under lock..."
 echo "go here..."
) 9>/tmp/mylockfile

J'ai ajouté le #!/bin/bash.

J'ai utilisé avec succès cette forme de flock.

Trevor Boyd Smith
la source