Un lock en shell

Publié le 29 février 2008 par Dxxcorp

Oui je sais, tout le monde sait faire, mais ce que je propose est un truc tout couillon et quasi automatique.

C’est venu du problème suivant: je récupère de gros fichiers de chez un collègue via rsync. Je le fais une fois par jour (via cron), et il se peut que la synchro prenne plus d’une journée. Et j’ai pas envie que mon script de synchro se lance plusieurs fois. C’est donc un problème d’instance: je ne veux qu’une instance de mon script à un moment donné.

Voilà la fonction adequat, avé les commentaires:

# Fournit un mécanisme de lock: empêche plusieurs instances

# de tourner en même temps.

# Et efface le fichier de lock en sortant

# Utilisation:

# lockme fichier_de_lock

lockme(){

# Fichier de lock: fichier passé en paramètre

lock=$1

# s'il existe, c'est qu'une instance du programme tourne, donc on sort, non sans avoir annoncé le numéro du process qui tournait (des qu'on voudrait le tuer )

if [ -e $lock ]

then

echo "An instance is running (`cat $lock`)." & exit

else

# sinon, je crée le fichier en y mettant le pid du process courant

echo "$$" > $lock

# Et là, c'est la ruse: je positionne un trap qui dit que quand le programme sort (le '0' à la fin) il efface le lock. Magique

trap "echo '(cleaning)' ; rm -f $lock" 0

fi

}

Exemple complet? Exemple complet.

touch test.sh

chmod +x test.sh

vi test.sh

#!/bin/bash

lockme(){

lock=$1

if [ -e $lock ]

then

echo "An instance is running (`cat $lock`)." & exit

else

echo "$$" > $lock

trap "echo '(cleaning)' ; rm -f $lock"

fi

}

# notez que le fichier de lock NE DOIT PAS être un truc du genre `mktemp -u`, sinon plusieurs instances tourneront inévitablement!

lock=/tmp/zetestlock

lockme $lock

sleep 1000

Puis faites:

./test.sh &

./test.sh

An instance is running (7937).

Yeah!

PS: Wordpress c’est de la m…. pour l’insertion de code.