
Quero executar vários scripts de shell Bash em paralelo. No entanto, quero evitar condições de corrida. O que são comandos Unixverdadeiramenteatômicos que eu poderia usar para esse fim, e como posso usá-los?
Responder1
#!/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
Isso garante que o código entre "(" e ")" seja executado apenas por um processo por vez e que o processo espere muito tempo por um bloqueio.
Responder2
Se lockfile
não estiver instalado no seu sistema, então mkdir
fará o trabalho: é uma operação atômica e falhará se o diretório já existir (desde que você não adicione a -p
opção de linha 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"
}
Responder3
lockfile(1) parece um bom candidato, mas esteja ciente de que faz parte doprocmailpacote, que talvez você ainda não tenha instalado em sua máquina. É um pacote popular o suficiente para ser empacotado para o seu sistema, caso ainda não esteja instalado. Três dos quatro sistemas que verifiquei possuem e o outro está disponível.
Usá-lo é simples:
#!/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
As opções que forneci fazem com que ele tente novamente uma vez por segundo por até 15 segundos. Solte o sinalizador "-r" se quiser esperar para sempre.
Responder4
Talvez o comando lockfile faça o que você precisa.
lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock