GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cuál es la mejor manera de garantizar que solo se ejecute una instancia de un script Bash?

El bloqueo de aviso se ha utilizado durante mucho tiempo y se puede utilizar en scripts de bash. Prefiero simple flock (de util-linux[-ng] ) más de lockfile (desde procmail ). Y recuerda siempre una trampa al salir (sigspec ==EXIT o 0 , atrapar señales específicas es superfluo) en esos scripts.

En 2009, lancé mi plantilla de script bloqueable (originalmente disponible en mi página wiki, hoy en día disponible como esencia). Transformar eso en una instancia por usuario es trivial. Al usarlo, también puede escribir fácilmente scripts para otros escenarios que requieran algún bloqueo o sincronización.

Aquí está el repetitivo mencionado para su conveniencia.

#!/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 el script es el mismo para todos los usuarios, puede usar un lockfile Acercarse. Si adquiere el bloqueo, continúe, de lo contrario, muestre un mensaje y salga.

Como ejemplo:

[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] $ 

Después de /tmp/the.lock ha sido adquirido, su script será el único con acceso a la ejecución. Cuando haya terminado, simplemente quite el candado. En forma de script, esto podría verse así:

#!/bin/bash

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

# Do stuff here

rm -f /tmp/the.lock

Creo que flock es probablemente la variante más fácil (y más memorable). Lo uso en un trabajo cron para autocodificar DVD y CD

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

Usa -w para tiempos de espera u omitir opciones para esperar hasta que se libere el bloqueo. Finalmente, la página de manual muestra un buen ejemplo para múltiples comandos:

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

Linux
  1. ¿Cuál es la mejor manera de detectar (a partir de un script) si el software está instalado?

  2. ¿La forma "adecuada" de probar si un servicio se está ejecutando en un script?

  3. ¿Cómo asegurarse de que solo se ejecute una instancia de un script Bash?

  4. ¿La mejor manera de garantizar que un script se ejecute una vez por período?

  5. ¿Cuál es la mejor manera de enviar una señal a todos los miembros de un grupo de procesos?

¿Cómo me aseguro de que solo se esté ejecutando una instancia de un script de Ruby a la vez?

Cualquier forma de salir del script bash, pero sin salir de la terminal

¿Cuál es el uso de $# en Bash?

¿Cuál es la diferencia entre ejecutar un script Bash y obtenerlo?

Acabo de eliminar /bin. ¿Cuál es la mejor manera de recuperarse?

¿Cuál es la forma más rápida de ejecutar un script?