
Quiero ejecutar varios scripts de shell Bash en paralelo. Sin embargo, quiero evitar las condiciones de carrera. ¿Qué son los comandos de Unix?realmenteatómicos que podría usar para este propósito, y ¿cómo puedo usarlos?
Respuesta1
#!/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 demasiado tiempo a que se bloquee.
Respuesta2
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 que no agregue el -p
modificador de línea de comandos).
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"
}
Respuesta3
lockfile(1) parece un buen candidato, aunque tenga en cuenta que es parte delcorreo electrónicopaquete, que es posible que aún no haya instalado en su máquina. Es un paquete lo suficientemente popular como para incluirlo en su sistema si aún no está instalado. Tres de los cuatro sistemas que revisé 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 le he dado hacen que se reintente una vez por segundo durante hasta 15 segundos. Suelta el indicador "-r" si quieres que espere para siempre.
Respuesta4
Quizás el comando lockfile haga lo que necesita.
lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock