GNU/Linux >> Tutoriels Linux >  >> Linux

Quelle est la meilleure façon de s'assurer qu'une seule instance d'un script Bash est en cours d'exécution ?

Le verrouillage consultatif est utilisé depuis des lustres et peut être utilisé dans les scripts bash. Je préfère le flock simple (à partir de util-linux[-ng] ) sur lockfile (à partir de procmail ). Et rappelez-vous toujours d'un piège à la sortie (sigspec ==EXIT ou 0 , le piégeage de signaux spécifiques est superflu) dans ces scripts.

En 2009, j'ai publié mon passe-partout de script verrouillable (disponible à l'origine sur ma page wiki, aujourd'hui disponible sous forme d'essentiel). Transformer cela en une instance par utilisateur est trivial. En l'utilisant, vous pouvez également facilement écrire des scripts pour d'autres scénarios nécessitant un verrouillage ou une synchronisation.

Voici le passe-partout mentionné pour votre commodité.

#!/bin/bash
# SPDX-License-Identifier: MIT

## Copyright (C) 2009 Przemyslaw Pawelczyk <[email protected]>
##
## This script is licensed under the terms of the MIT license.
## https://opensource.org/licenses/MIT
#
# Lockable script boilerplate

### HEADER ###

LOCKFILE="/var/lock/`basename $0`"
LOCKFD=99

# PRIVATE
_lock()             { flock -$1 $LOCKFD; }
_no_more_locking()  { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking()  { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }

# ON START
_prepare_locking

# PUBLIC
exlock_now()        { _lock xn; }  # obtain an exclusive lock immediately or fail
exlock()            { _lock x; }   # obtain an exclusive lock
shlock()            { _lock s; }   # obtain a shared lock
unlock()            { _lock u; }   # drop a lock

### BEGIN OF SCRIPT ###

# Simplest example is avoiding running multiple instances of script.
exlock_now || exit 1

# Remember! Lock file is removed when one of the scripts exits and it is
#           the only script holding the lock or lock is not acquired at all.

Si le script est le même pour tous les utilisateurs, vous pouvez utiliser un lockfile approcher. Si vous acquérez le verrou, continuez, sinon affichez un message et quittez.

Par exemple :

[Terminal #1] $ lockfile -r 0 /tmp/the.lock
[Terminal #1] $ 

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] lockfile: Sorry, giving up on "/tmp/the.lock"

[Terminal #1] $ rm -f /tmp/the.lock
[Terminal #1] $ 

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] $ 

Après /tmp/the.lock a été acquis votre script sera le seul à avoir accès à l'exécution. Lorsque vous avez terminé, retirez simplement le verrou. Sous forme de script, cela pourrait ressembler à :

#!/bin/bash

lockfile -r 0 /tmp/the.lock || exit 1

# Do stuff here

rm -f /tmp/the.lock

Je pense flock est probablement la variante la plus facile (et la plus mémorable). Je l'utilise dans une tâche cron pour encoder automatiquement des DVD et des CD

# try to run a command, but fail immediately if it's already running
flock -n /var/lock/myjob.lock   my_bash_command

Utilisez -w pour les délais d'attente ou laissez les options d'attente jusqu'à ce que le verrou soit libéré. Enfin, la page de manuel montre un bel exemple pour plusieurs commandes :

   (
     flock -n 9 || exit 1
     # ... commands executed under lock ...
   ) 9>/var/lock/mylockfile

Linux
  1. La meilleure façon de détecter (à partir d'un script) si un logiciel est installé ?

  2. Comment s'assurer qu'une seule instance d'un script Bash s'exécute ?

  3. N'importe quel moyen de quitter le script bash, mais sans quitter le terminal

  4. Quelle est la meilleure façon de gérer les conditions de mémoire insuffisante en Java ?

  5. À quoi sert $# dans Bash

Quelle est la meilleure façon d'envoyer un signal à tous les membres d'un groupe de processus ?

Comment puis-je m'assurer qu'une seule instance d'un script Ruby s'exécute à la fois ?

Limiter un programme graphique sous Linux à une seule instance

Est-il possible de récupérer le contenu d'un script bash en cours d'exécution à partir de la RAM

Je viens de supprimer /bin. Quelle est la meilleure façon de récupérer ?

Quel est le moyen le plus rapide d'exécuter un script ?