web-development-kb-pt.site

Quais comandos do Unix podem ser usados ​​como um semáforo / bloqueio?

Quero executar vários scripts do Bash Shell em paralelo. No entanto, quero evitar as condições da corrida. Quais comandos do Unix são verdadeiramente atômicos que eu poderia usar para esse fim, e como posso usá-los?

39
Larry Wang

Se lockfile não estiver instalado no seu sistema, mkdir fará o trabalho: é uma operação atômica e falhará se o diretório já existir (desde que você não adicione o -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"
}
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

Isso garante que o código entre "(" e ")" seja executado apenas por um processo por vez e que o processo aguarde um bloqueio por muito tempo.

30
Alex B

o lockfile (1) parece um bom candidato, apesar de ser parte do pacote procmail , que talvez você ainda não tenha instalado em sua máquina. É um pacote bastante popular que deve ser empacotado para o seu sistema se ainda não estiver instalado. Três dos quatro sistemas que verifiquei o 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 eu forneci fazem com que tente novamente uma vez por segundo por até 15 segundos. Solte a bandeira "-r" se desejar que ela espere para sempre.

12
Warren Young

A chamada do sistema mkdir() é atômica nos sistemas de arquivos POSIX. Portanto, o uso do comando mkdir de forma que envolva exatamente uma chamada para mkdir() atingiria seu objetivo. (IOW, não use mkdir -p). O desbloqueio correspondente é rmdir, é claro.

Advertência emptor: mkdir() pode não ser atômico nos sistemas de arquivos da rede.

7
Hari

Talvez o comando lockfile faça o que você precisa.

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

Se você estiver rodando apenas no Unix, use fifos. Você pode gravar registros de trabalho no fifo e fazer com que os processos sejam lidos neste arquivo, e seus leitores bloquearão o fifo.

Os arquivos de bloqueio estão ok, mas pelo que você descreve, eu usaria fifos

1
Chris

Conforme publicado aqui: " Bloqueio correto nos scripts do Shell? ", usando a ferramenta FLOM (Free LOck Manager) , serializando comandos e scripts do Shell se torna tão fácil quanto executar

flom -- command_to_serialize

O FLOM permite implementar casos de uso mais sofisticados (bloqueio distribuído, leitores/gravadores, recursos numéricos, etc ...) conforme explicado aqui: http://sourceforge.net/p/flom/wiki/FLOM%20by % 20exemplos /

0
tiian