systemd reiniciar trabalhos sob condição

1

Eu tenho um daemon somente do Windows rodando em uma caixa linux com wine e Xvfb. Devido a esta configuração bastante experimental, o daemon trava periodicamente e eu gostaria de implementar algum tipo de mecanismo para reiniciar automaticamente o daemon. Atualmente eu tenho uma definição de unidade systemd com a configuração Restart=always .

No entanto, notei que às vezes o daemon falha, mas não sai do processo. Isso é o equivalente a exibir uma caixa de diálogo com a pergunta "O daemon está travado, você deseja enviar um relatório de erro?". Portanto, o processo ainda está em execução, mas o daemon parou de funcionar.

O único comportamento externo desse fenômeno que eu posso examinar na minha caixa linux são dois novos arquivos, que aparecem em um determinado local, mas com nomes de arquivos variáveis (são dependentes do tempo e possuem um registro de data e hora em seu nome). Eu acho que eles são algum tipo de despejo de memória ou rastreamentos de pilha que devem ser originalmente usados para o envio do relatório de erro.

Agora, estou procurando uma solução para o systemd capturar essa solução, como

  1. No início da unidade, observe o diretório de destino do dump de falha e faça um instantâneo do conteúdo do diretório
  2. Iniciar o daemon
  3. Observe periodicamente o diretório e, se houver novos arquivos, que não estão no instantâneo, com base em alguma expressão regular, reinicie o daemon e atualize o instantâneo.

Eu pensei em um wrapper, escrito em bash ou algo assim, mas há dois problemas: primeiro eu não saberia como implementar esse comportamento e, segundo, isso tornaria o uso do systemd completamente obsoleto, já que o script lida com todos o tratamento de falhas e o systemd só executaria o script.

Eu também pensei em apenas reiniciar periodicamente o daemon com os recursos fornecidos pelo systemd, mas isso seria bastante ineficiente (dado o fato de que um daemon do Windows em um invólucro de vinho não é ineficiente em primeiro lugar), já que seria reiniciado o daemon, por vezes, quando não é necessário, ou levaria algum tempo após o daemon travar até a reinicialização periódica entrar em ação.

Qual seria a melhor solução para resolver este problema?

E apenas para os registros: o daemon de que estou falando é o aplicativo de upload do Google Fotos. O Google, por algum motivo, não o libera para o Linux.

    
por simonszu 02.03.2017 / 09:15

2 respostas

4

Ok, descobri o poder do systemd.path.

Eu criei uma segunda unidade de serviço com ExecStart=systemctl restart daemon.unit e Type=oneshot . Depois disso, criei uma terceira unidade, uma unidade de caminho com PathModified=<crashdump output directory> e Unit=daemon-restart.unit .

Funciona agora. Eu só tenho que ter certeza de que nenhum outro processo está escrevendo para o diretório de saída, mas isso é solucionável com várias diferentes precisões de vinhos.

    
por 02.03.2017 / 10:33
1

Eu acho que o seu problema é que o seu programa pode estar falhando, mas o vinho não está, então o systemd não vê nada errado (o PID ainda está por aí).

Em primeiro lugar, você pode encontrar alguma ajuda nas respostas a essa pergunta: Iniciar o serviço do SystemD condicionalmente

Eu acho que você pode precisar detalhar suas necessidades um pouco mais (e / ou, considere ajustá-las para simplificar a configuração).

Basicamente, acho que a solução se resumirá ao uso inteligente de ConditionPathExistsGlob =, possivelmente em uma unidade auxiliar.

Uma solução hacky pode envolver uma unidade temporizada com essa condição PathExistsGlob, que pode estar reiniciando seu serviço principal. Eu tenderia a querer que essa unidade temporizadora também lidasse com a limpeza de arquivos / lixeiras, em vez de fazer a unidade principal fazê-lo, mas isso é quase certamente uma questão de gosto.

Então, eu não tocaria no que você tem, mas em vez disso, adicione algo como (NB: Isso é um palpite, e não testado):

[Unit]
Description=Detect and recover issues with Uploader
After=uploader.service
Requires=uploader.service
PartOf=uploader.service
AssertPathExistsGlob=/srv/uploader/crash*.dump

[Service]
Type=oneshot
ExecStart=cleanup_script
Restart=on-success

A lógica básica é:

  • você executa isso em um timer, digamos a cada 5 minutos (ou o que for que faça sentido para as suas necessidades)
  • se os arquivos de travamento não estiverem lá, a unidade do cronômetro não iniciará e o serviço principal do Uploader continuará mantendo
  • se os arquivos de travamento estiverem lá, execute algum script personalizado para fazer a coisa certa com eles e reinicie nossa unidade de timer (que, por causa da PartOf, deve também reiniciar o serviço principal do Uploader)

Não estou dizendo que essa é uma ótima solução, mas pode ser uma solução

    
por 02.03.2017 / 10:36