monit: verificar processo sem pidfile

36

Estou procurando uma maneira de eliminar todos os processos com um determinado nome que estejam em execução há mais de X tempo. Gero muitas instâncias desse executável específico e, às vezes, entra em um estado ruim e é executado para sempre, ocupando muito CPU.

Eu já estou usando o monit, mas não sei como verificar um processo sem um arquivo pid. A regra seria algo como isto:

kill all processes named xxxx that have a running time greater than 2 minutes

Como você expressaria isso em monit?

Parand
fonte
( você deve marcar uma resposta aqui )
ewwhite

Respostas:

80

No monit, você pode usar uma sequência correspondente para processos que não possuem um PID. Usando o exemplo de um processo chamado "myprocessname",

check process myprocessname
        matching "myprocessname"
        start program = "/etc/init.d/myproccessname start"
        stop program = "/usr/bin/killall myprocessname"
        if cpu usage > 95% for 10 cycles then restart

Talvez se você verificar se a carga da CPU está em um determinado nível por 10 ciclos de monitoramento (de 30 segundos cada), reiniciar ou interromper, isso poderia ser uma opção. Ou você pode usar o teste de carimbo de data / hora do monit em um arquivo relacionado ao processo.

ewwhite
fonte
1
Tenha cuidado: ele não vai trabalhar com isso há mais de um processo
Rux
1
você pode usar uma expressão regular: matchin "othertuff. * myprocessname"
user174962 8/17/17
@ruX: o que acontece se vários processos relacionados corresponderem? Como eles podem lidar?
kontextify
É preciso a primeira partida.
ewwhite 31/10
5

Não existe ferramenta pronta para uso com essa funcionalidade. Vamos supor que você queira matar scripts php-cgi, que são executados por mais de um minuto. Fazem isto:

pgrep php-cgi | xargs ps -o pid,time | perl -ne 'print "$1 " if /^\s*([0-9]+) ([0-9]+:[0-9]+:[0-9]+)/ && $2 gt "00:01:00"' | xargs kill

pgrepselecionará processos pelo nome, ps -o pid,timeimprime o tempo de execução de cada pid e, em seguida, analisa a linha, extrai o tempo dela e imprime o pid se o tempo comparar com o definido. resultado passado para matar.

datacompboy
fonte
o processo em execução por muito tempo obtém um tempo de execução estranho (62-13: 53: 05), portanto, o tempo de execução da análise de expressões regulares deve ser ([-0-9] +: [0-9] +: [0-9] + ) - observe o sinal de menos no início da expressão.
22614
3

Resolvi esse problema exato com o ps-watcher e escrevi sobre isso no linux.com alguns anos atrás. O ps-watcher permite monitorar processos e eliminá-los com base no tempo de execução acumulado. Aqui está a configuração relevante do ps-watcher, supondo que seu processo seja chamado 'foo':

[foo]
  occurs = every
  trigger = elapsed2secs('$time') > 1*HOURS && $ppid != 1
  action = <<EOT
  echo "$command accumulated too much CPU time" | /bin/mail user\@host
  kill -TERM $pid
EOT

[foo?]
   occurs = none
   action = /usr/local/etc/foo restart

A chave é a linha

trigger = elapsed2secs('$time') > 1*HOURS && $ppid != 1`

que diz 'se o tempo acumulado do processo for> 1 hora E eu não for o processo pai, reinicie-me.

Então, eu sei que a resposta não usa monit, mas funciona. O ps-watcher é leve e simples de configurar, portanto não há nenhum problema em executá-lo além da sua configuração de monit.

Phil Hollenback
fonte
3

O Monit pode fazer isso a partir da versão 5.4:

if uptime > 3 days then restart

Veja: o arquivo CHANGES do projeto

David Radcliffe
fonte
0

Você pode trabalhar isso no monit como uma declaração executiva.

    if [[ "$(uname)" = "Linux" ]];then killall --older-than 2m someprocessname;fi
Jodie C
fonte