Evite arquivos PID, crons ou qualquer outra coisa que tente avaliar processos que não são filhos deles.
Há uma boa razão pela qual, no UNIX, você só pode esperar seus filhos. Qualquer método (ps parsing, pgrep, armazenando um PID, ...) que tente solucionar o problema é defeituoso e possui buracos escancarados. Apenas diga não .
Em vez disso, você precisa do processo que monitora seu processo para ser o pai do processo. O que isto significa? Isso significa que apenas o processo que inicia o processo pode esperar com segurança que ele termine. No bash, isso é absolutamente trivial.
until myserver; do
echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2
sleep 1
done
A parte acima do código do bash é executada myserver
em um until
loop. A primeira linha inicia myserver
e aguarda o término. Quando termina, until
verifica seu status de saída. Se o status de saída for 0
, significa que ele terminou normalmente (o que significa que você solicitou o desligamento de alguma forma e o fez com êxito). Nesse caso, não queremos reiniciá-lo (apenas pedimos para desligar!). Se o status de saída não for 0
, until
executará o corpo do loop, que emite uma mensagem de erro no STDERR e reinicia o loop (de volta à linha 1) após 1 segundo .
Por que esperamos um segundo? Porque se algo estiver errado com a sequência de inicialização myserver
e ela travar imediatamente, você terá um loop muito intenso de reinicializações e travamentos constantes em suas mãos. O sleep 1
tira a tensão disso.
Agora tudo o que você precisa fazer é iniciar esse script bash (de forma assíncrona, provavelmente), e ele será monitorado myserver
e reiniciado conforme necessário. Se você deseja iniciar o monitor na inicialização (fazendo o servidor "sobreviver" à reinicialização), é possível agendá-lo no cron (1) do usuário com uma @reboot
regra. Abra suas regras cron com crontab
:
crontab -e
Em seguida, adicione uma regra para iniciar o script do seu monitor:
@reboot /usr/local/bin/myservermonitor
Alternativamente; veja inittab (5) e / etc / inittab. Você pode adicionar uma linha para myserver
iniciar em um determinado nível de inicialização e ser reaparecida automaticamente.
Editar.
Deixe-me adicionar algumas informações sobre por que não usar arquivos PID. Enquanto eles são muito populares; eles também são muito falhos e não há razão para que você não faça da maneira correta.
Considere isto:
Reciclagem de PID (acabando com o processo errado):
/etc/init.d/foo start
: inicie foo
, escreva foo
o PID para/var/run/foo.pid
- Um tempo depois:
foo
morre de alguma forma.
- Um pouco mais tarde: qualquer processo aleatório que inicie (chame
bar
) leva um PID aleatório, imagine-o usando foo
o antigo PID.
- Você percebe que se
foo
foi: /etc/init.d/foo/restart
lê /var/run/foo.pid
, checa para ver se ainda está vivo, acha bar
, acha que está foo
, mata, inicia um novo foo
.
Os arquivos PID ficam obsoletos. Você precisa de lógica excessivamente complicada (ou devo dizer, não trivial) para verificar se o arquivo PID está obsoleto e se essa lógica está novamente vulnerável 1.
.
E se você nem tiver acesso de gravação ou estiver em um ambiente somente leitura?
É supercomplicação inútil; veja como é simples o meu exemplo acima. Não há necessidade de complicar isso.
Veja também: Os arquivos PID ainda são defeituosos ao fazê-lo 'certo'?
A propósito; ainda pior do que os arquivos PID está analisando ps
! Nunca faça isso.
ps
é muito portável. Enquanto você o encontra em quase todos os sistemas UNIX; seus argumentos variam muito se você deseja saída fora do padrão. E a saída padrão é APENAS para consumo humano, não para análise por script!
- A análise
ps
leva a muitos falsos positivos. Pegue o ps aux | grep PID
exemplo e agora imagine alguém iniciando um processo com um número em algum lugar, como argumento que é o mesmo que o PID com o qual você olhou seu daemon! Imagine duas pessoas iniciando uma sessão do X e você esperando que o X mate a sua. É apenas todo tipo de coisa ruim.
Se você não deseja gerenciar o processo sozinho; existem alguns sistemas perfeitamente bons por aí que atuam como monitor para seus processos. Veja runit , por exemplo.