Antecedentes
Aqui está o que eu quero alcançar. Eu tenho um processo (potencialmente) de longa duração. Agora tenho um bom encaixe e tudo está em ordem.
No entanto, como este é um trabalho agendado, o script será executado novamente e novamente. No script real que tenho, um arquivo registra essa contagem de falhas. Quando atinge um limite, um e-mail é enviado para o administrador, caso o script original se torne um zumbi ou esteja preso. Se o limite for atingido e o processo inicial que afirma que o bloqueio não está mais ativo, o bloqueio é interrompido e um texto alternativo é enviado ao administrador informando sobre a condição. Tudo isso provavelmente não é relevante para o problema, mas quero dar uma visão completa aqui.
Sempre que o limite é atingido, a contagem de falhas no arquivo é redefinida e inicia novamente a partir daí. A instância original pode ou não não conseguir ver o arquivo de contagem de falhas.
A instância de script original que segurou o bloqueio terminará (esperançosamente) seu trabalho e sairá.
Pergunta
Como posso implementar um esquema pelo qual as instâncias "com falha" que encontram o bloqueio enviam um sinal (tentei SIGUSR1
) para a instância original e a instância original controla quantas vezes ele foi "pingado"?
Aqui está o script de teste que eu criei até agora:
#!/usr/bin/env bash
LOCKFILE=/tmp/$(basename $0).lock
let COUNTER=0
function concurrent_run
{
let COUNTER=COUNTER+1
echo -e "\ncaught SIGUSR1 (counter = $COUNTER)"
}
if ( set -o noclobber; echo "$$" > "$LOCKFILE" ) 2> /dev/null; then
trap 'rm -f "$LOCKFILE"; exit $?' INT TERM EXIT
trap concurrent_run USR1
echo "I was first, going to sleep"
sleep 100000
trap - INT TERM EXIT USR1
else
LOCKPID=$(cat "$LOCKFILE")
echo "Lock already held by $LOCKPID"
[[ -n "$LOCKPID" ]] && kill -0 $LOCKPID && { kill -USR1 $LOCKPID; echo "... knock knock? ($LOCKPID)"; }
exit 1
fi
echo "End: $COUNTER"
exit 0
(o sleep
está imitando o trabalho de longa duração executado pelo script real)
Estou testando no Linux e tentei o nome do sinal como USR1
e SIGUSR1
, ambos fornecendo o mesmo resultado (ou seja, nenhum).
builtin trap -l
me deu 10 como SIGUSR1
, então também tentei um manual kill -10 PID
no PID
da instância original. Infelizmente não consigo ver o sinal.
O que estou fazendo de errado?
Como testar
Inicie uma instância do script (eu a denominei sigtest
):
$ ./sigtest
I was first, going to sleep
Inicie uma segunda instância do script em outro terminal, janela, painel (mesmo usuário!):
$ ./sigtest
Lock already held by 15360
... knock knock? (15360)
Repita ...
Resultado esperado no primeiro terminal (ignorando linhas vazias):
caught SIGUSR1 (counter = 1)
caught SIGUSR1 (counter = 2)
caught SIGUSR1 (counter = 3)
caught SIGUSR1 (counter = 4)
Versão do Bash
$ echo $BASH_VERSION
4.1.5(1)-release