flock: Prevenindo Execucoes Simultaneas com Bloqueio de Arquivo

flock: Prevenindo Execucoes Simultaneas com Bloqueio de Arquivo

O Que e flock?

Conclusao: flock e um comando do util-linux que usa um bloqueio baseado em arquivo para impedir que um script ou tarefa seja executado duas vezes ao mesmo tempo, em uma unica linha.

O que voce vai aprender:

  • O padrao para prevenir sobreposicao de cron jobs com flock
  • Quando usar os modos exclusivo / compartilhado / nao-bloqueante / timeout
  • Um snippet pronto para autolock de um script

Os padroes praticos

  • Proteger um unico comando --> flock -n /var/lock/job.lock cmd
  • Proteger um script inteiro --> coloque o boilerplate FLOCKER no inicio
  • Quer esperar --> -w segundos; falhar imediatamente --> -n

Premissas (ambiente alvo)

  • flock vem com o util-linux e esta presente em praticamente todas as distros Linux
  • Bloqueios sao advisories (cooperativos): so se aplicam entre processos que usam flock
  • Suporte em NFS / CIFS e limitado (coberto abaixo)

Por Que Prevenir Execucoes Simultaneas?

Conclusao: Se um backup ou tarefa batch reinicia enquanto a execucao anterior ainda esta em andamento, voce arrisca corrupcao de dados, processamento duplicado e carga descontrolada. O flock previne a sobreposicao estruturalmente.

Suponha que uma tarefa batch execute a cada 5 minutos via cron, mas uma execucao leva mais de 5 minutos. A proxima execucao sobrepoe a anterior, e dois processos escrevem no mesmo arquivo ao mesmo tempo. O resultado tipico e um dos seguintes:

  • Arquivos de saida e logs corrompidos ou intercalados
  • Processamento duplicado (emails duplos, cobranca dupla)
  • Processos acumulando e esgotando memoria / CPU

Voce poderia gerenciar um lockfile PID manualmente, mas se o processo morrer via kill -9 ou perda de energia, um lock obsoleto permanece e futuras execucoes nunca iniciam. Com flock, o kernel libera o bloqueio automaticamente quando o processo termina, entao nao ha limpeza para fazer.

Como Usar o flock?

Conclusao: A forma basica e flock lockfile comando. O lockfile e criado automaticamente se nao existir, e o bloqueio e liberado no momento em que o comando termina.

flock tem tres sintaxes.

# Forma 1: bloquear um arquivo/diretorio e executar um comando
flock /var/lock/mytask.lock command args

# Forma 2: executar um unico comando pelo shell com -c
flock /var/lock/mytask.lock -c 'command1 && command2'

# Forma 3: bloquear um numero de file descriptor ja aberto
flock 200

Um exemplo minimo. Execute echo mantendo um bloqueio exclusivo:

flock -x /tmp/myapp.lock echo 'executando sob bloqueio'
  • O lockfile (/tmp/myapp.lock) e criado se nao existir
  • -x solicita um bloqueio exclusivo (e o padrao, entao pode ser omitido)
  • O bloqueio e liberado assim que echo termina

O lockfile e uma "chave", nao "dados". Pode estar vazio, e voce nunca precisa exclui-lo. Deixar o arquivo no lugar nao causa problema, porque o estado do bloqueio esta vinculado ao file descriptor aberto, nao a existencia do arquivo.

Quais Sao as Principais Opcoes do flock?

Conclusao: As quatro que voce precisa conhecer sao -n (nao esperar), -w (limite de tempo), -s (compartilhado) e -E (codigo de saida em falha).

Opcao Significado
-x, --exclusive Bloqueio exclusivo (escrita). Padrao
-s, --shared Bloqueio compartilhado (leitura). Multiplos detentores permitidos
-n, --nonblock Falhar imediatamente em vez de esperar (codigo de saida 1)
-w, --timeout sec Esperar ate N segundos, depois falhar. Fracoes permitidas (-w 0.5)
-u, --unlock Liberar o bloqueio explicitamente
-E, --conflict-exit-code N Codigo de saida em falha -n / -w (padrao 1)
-o, --close Fechar o fd antes de executar o comando (filho nao o mantea)
-c, --command Executar um unico comando pelo shell (sh -c)

-w 0 e equivalente a --nonblock (zero segundos de espera significa nenhuma espera).

Como Impedir que um cron Job Se Sobreponha?

Conclusao: Envolva a linha do cron em flock -n lockfile. Se a execucao anterior ainda estiver em andamento, esta execucao sai silenciosamente e nenhuma sobreposicao ocorre.

Este e o caso de uso mais comum do flock. Escreva a linha do crontab assim:

# Backup a cada 5 minutos. Pular esta execucao se a anterior ainda estiver em andamento.
*/5 * * * * /usr/bin/flock -n /var/lock/backup.lock /opt/scripts/backup.sh
  • -n significa sair imediatamente em sobreposicao (pular em vez de esperar)
  • Se a tarefa anterior terminou, o bloqueio e adquirido e a tarefa executa
  • Por convencao, coloque o lockfile em /var/lock/ ou /run/lock/

Se voce preferir esperar um pouco quando as execucoes se sobrepuserem, use -w:

# Esperar ate 30 segundos, depois desistir
*/5 * * * * /usr/bin/flock -w 30 /var/lock/backup.lock /opt/scripts/backup.sh

Dentro do cron, escreva flock como um caminho absoluto (/usr/bin/flock) para que funcione mesmo quando o PATH e minimo.

Como Fazer um Script se Auto-Bloquear?

Conclusao: Coloque um bloco de file descriptor ou o boilerplate FLOCKER no inicio do script, e ele se protege contra execucoes simultaneas independentemente de como e invocado.

Em vez de escrever flock em cada linha do cron, construa o bloqueio dentro do proprio script. Dois padroes comuns.

Padrao 1: Abordagem com file descriptor

#!/bin/bash
exec 200>/var/lock/myscript.lock
flock -n 200 || { echo "ja em execucao"; exit 1; }

# --- tudo abaixo executa como uma secao critica exclusiva ---
echo "fazendo trabalho..."
sleep 10
  • exec 200>... abre o lockfile no fd 200 (200 e uma convencao; qualquer numero livre de 9-255 funciona)
  • flock -n 200 bloqueia esse fd; se nao puder, o branch || sai
  • Quando o script termina, o fd fecha e o bloqueio e liberado automaticamente

Padrao 2: Boilerplate FLOCKER (do man page)

#!/bin/bash
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :

# --- tudo abaixo sempre executa sob o bloqueio ---
echo "fazendo trabalho..."

Isso usa o proprio script como lockfile e verifica a variavel de ambiente FLOCKER para decidir se ja re-executou atraves do flock. Cole no inicio e o autolock esta feito.

Quando voce bloqueia o proprio arquivo do script (flock -en "$0"), nao funciona bem com scripts que se reescrevem via > (scripts auto-atualizaveis). E mais seguro bloquear um arquivo dedicado que voce nunca sobrescreve.

Nao-Bloqueante vs Timeout: Qual Usar?

Conclusao: Use -n se nao houver problema em descartar a execucao sobreposta; use -w segundos se uma breve espera permitir que o trabalho prossiga. Verifique o codigo de saida para detectar falha.

# Falhar imediatamente (para batches onde pular uma sobreposicao e aceitavel)
flock -n /var/lock/job.lock ./job.sh

# Esperar ate 10 segundos (para trabalho onde uma breve contencao deve ser absorvida)
flock -w 10 /var/lock/job.lock ./job.sh

Detecte se o bloqueio falhou verificando o codigo de saida. Quando -n / -w falha, o codigo de saida e 1 por padrao e pode ser alterado com -E.

flock -n -E 99 /var/lock/job.lock ./job.sh
if [ $? -eq 99 ]; then
    echo "pulado porque outro processo esta em execucao"
fi

Se o bloqueio for bem-sucedido e o comando executar, o codigo de saida do flock e o proprio codigo de saida do comando. Escolha um valor -E que seu comando nunca retorne, para distinguir uma falha de bloqueio de um resultado real do comando.

Quais Sao as Armadilhas Comuns do flock?

Conclusao: As principais armadilhas sao falta de suporte em NFS, perda do bloqueio ao recriar o arquivo de dados com >, e a localizacao do lockfile.

2. Recriar o arquivo de dados remove o bloqueio

O bloqueio esta vinculado ao file descriptor aberto. Se voce bloquear o arquivo de dados de saida e depois reconstrui-lo com >, o inode muda e o bloqueio perde o sentido.

# Ruim: bloquear data.txt enquanto recria data.txt
flock data.txt sh -c '> data.txt; generate >> data.txt'

Bloqueie um lockfile dedicado que voce nunca sobrescreve.

3. flock nao detecta deadlock

Se multiplos bloqueios forem obtidos em ordem cruzada, podem ocorrer deadlocks, mas flock em si nao os detecta. Mantenha um bloqueio por script e evite designs que abranjam multiplos bloqueios.

Evite essas armadilhas e o flock se torna uma forma poderosa e robusta de eliminar execucoes simultaneas em poucos caracteres.

Resumo e Proxima Leitura