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