it-swarm-es.tech

¿Qué comandos de Unix se pueden usar como semáforo / bloqueo?

Quiero ejecutar múltiples scripts de Bash Shell en paralelo. Sin embargo, quiero evitar las condiciones de carrera. ¿Qué comandos de Unix son verdaderamente atómicos que podría usar para este propósito, y cómo puedo usarlos?

39
Larry Wang

Si lockfile no está instalado en su sistema, entonces mkdir hará el trabajo: es una operación atómica, y falla si el directorio ya existe (siempre y cuando no agregue el -p interruptor de línea de comando).

create_lock_or_wait () {
  path="$1"
  wait_time="${2:-10}"
  while true; do
        if mkdir "${path}.lock.d"; then
           break;
        fi
        sleep $wait_time
  done
}

remove_lock () {
  path="$1"
  rmdir "${path}.lock.d"
}
35
Riccardo Murri

flock(1)

#!/bin/bash

# Makes sure we exit if flock fails.
set -e

(
  # Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
  flock -x -w 10 200

  # Do stuff

) 200>/var/lock/.myscript.exclusivelock

Esto garantiza que el código entre "(" y ")" se ejecute solo por un proceso a la vez y que el proceso espere un bloqueo demasiado tiempo.

30
Alex B

lockfile (1) parece un buen candidato, aunque tenga en cuenta que es parte del paquete procmail , que es posible que aún no haya instalado en su máquina. Es un paquete suficientemente popular que debería empaquetarse para su sistema si aún no está instalado. Tres de los cuatro sistemas que verifiqué lo tienen, y el otro lo tiene disponible.

Usarlo es simple:

#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`

echo Waiting for lock $LOCKFILE...
if lockfile -1 -r15 $LOCKFILE
then
    # Do protected stuff here
    echo Doing protected stuff...

    # Then, afterward, clean up so another instance of this script can run
    rm -f $LOCKFILE
else
    echo "Failed to acquire lock!  lockfile(1) returned $?"
    exit 1
fi

Las opciones que he dado hacen que vuelva a intentarlo una vez por segundo durante hasta 15 segundos. Suelta la bandera "-r" si quieres que espere para siempre.

12
Warren Young

La llamada al sistema mkdir() es atómica en los sistemas de archivos POSIX. Por lo tanto, usar el comando mkdir de tal manera que implique exactamente una llamada a mkdir() lograría su propósito. (IOW, no uses mkdir -p). El desbloqueo correspondiente es rmdir, por supuesto.

Advertencia: mkdir() podría no ser atómica en los sistemas de archivos de red.

7
Hari

Tal vez el comando lockfile hará lo que necesita.

lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock
3
jacksonh

Si solo está ejecutando en Unix, use fifos. Puede escribir registros de trabajo en el Fifo y hacer que los procesos lean de este archivo y sus lectores bloquearán en el Fifos.

Los archivos de bloqueo están bien, pero por lo que describe iría con fifos

1
Chris

Como se publica aquí: " ¿Bloqueo correcto en los scripts de Shell? ", usando la herramienta FLOM (Free LOck Manager) , serializar comandos y scripts de Shell se vuelve tan fácil como ejecutar

flom -- command_to_serialize

FLOM le permite implementar casos de uso más sofisticados (bloqueo distribuido, lectores/escritores, recursos numéricos, etc.) como se explica aquí: http://sourceforge.net/p/flom/wiki/FLOM%20by % 20examples /

0
tiian