Descubra o que o processo apache de alto uso da CPU está realmente fazendo?

18

Atualmente, temos alguns problemas com nosso servidor, nos quais, de forma intermitente, parecemos obter processos apache que simplesmente rodam e rodam, ocupando 100% da CPU.

Ao executar o topo, vemos o seguinte:

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
20788 www-data  20   0  318m  18m 3984 R  100  0.0  40:29.21 /usr/sbin/apache2 -k start
23523 www-data  20   0  319m  20m 4684 R  100  0.0   4:12.36 /usr/sbin/apache2 -k start

Quero tentar descobrir qual script (ou o que é) está causando isso, então tentei:

 strace -p 20788

Mas isso não mostra nenhuma saída (deixei por cerca de 10 minutos e não mostra nada). Pelo meu entendimento, isso pode significar que ele está preso em um loop infinito e não há nenhuma "chamada do sistema" para mostrar.

Há mais alguma coisa que eu possa fazer para mostrar o que está acontecendo?

obrigado

Editar - Esqueci de mencionar, este é um servidor ativo com algumas centenas de usuários a qualquer momento! Portanto, não posso realmente tentar livremente alterar as opções de configuração e reiniciar o apache.

Edit 2 - O backtrace (bt) do gdb não parece ser tão útil quando o PHP não está configurado com --enable-debug - ele mostra apenas "execute ()", mas eu preciso saber o que é o script PHP realmente correndo .. existe alguma outra maneira?

#0  0x00007f6c143fb0c5 in ?? () from /usr/lib/apache2/modules/libphp5.so
#1  0x00007f6c143b040b in execute () from /usr/lib/apache2/modules/libphp5.so
#2  0x00007f6c1438b970 in zend_execute_scripts () from     /usr/lib/apache2/modules/libphp5.so
#3  0x00007f6c14337fe3 in php_execute_script () from     /usr/lib/apache2/modules/libphp5.so
#4  0x00007f6c1441ae7d in ?? () from /usr/lib/apache2/modules/libphp5.so
#5  0x00007f6c18912508 in ap_run_handler ()
#6  0x00007f6c1891297e in ap_invoke_handler ()
#7  0x00007f6c18922570 in ap_process_request ()
#8  0x00007f6c1891f398 in ?? ()
#9  0x00007f6c18918fa8 in ap_run_process_connection ()
#10 0x00007f6c189271d0 in ?? ()
#11 0x00007f6c1892793a in ?? ()
#12 0x00007f6c189284e7 in ap_mpm_run ()
#13 0x00007f6c188fd4a4 in main ()
BT643
fonte
11
O Apache suporta reinicialização "graciosa", então por que não?
13133 poige
11
Acho que quando tentamos anteriormente, não foi possível reiniciar normalmente por causa dos processos apache "presos" ... embora isso possa estar errado, isso foi há um tempo atrás.
BT643
Outro truque é executar outra instância do apache em porta diferente, redirecionando novas conexões para ele.
13133 poige

Respostas:

9

Bem, caso você esteja se sentindo corajoso:

gdb -p 20788

emita btpara ver o quadro da pilha, por exemplo

E BTW, há também ltrace para mencionar - tente também.

UPD. : bem, ok, já que agora temos uma ideia de que o Apache está realmente executando alguma coisa, por que você não olhava para a mod_statussaída - uma estendida ?

poige
fonte
gdb não está instalado :( terá que esperar até que eu voltar ao trabalho amanhã para ver se eu posso instalá-lo sem causar quaisquer problemas .. ltracenão mostrar qualquer saída também.
BT643
Acabei de adicionar os resultados do gdb bt no post inicial .. realmente não me diz muita coisa!
BT643
Oh, que bom que eu sugeri a direção certa. )
poige 14/03
@ BT643, consulte UPD.
poige
4
O mod_status realizado já estava ativado por padrão, limitando-se a acessar a partir de 127.0.0.1. Acabei de fazer login via SSH e canalizei a saída para um arquivo curl domain.com/server-status > randomfile.html- depois vi o arquivo. Acabou que era um código antigo de desenvolvedores que fica preso em um loop (arquivo PHP)! Tudo ordenado agora. Obrigado pela ajuda :)
BT643
2

Uma abordagem muito fácil é usar htop. Você pode classificar os processos de alta CPU e usar

  • s para straceum processo
  • l para lsofver os arquivos abertos de um processo
  • L para ltrace.

Descobri que pelo menos uma dessas opções encontra o script que gera a carga e, é claro, você pode usá-lo em um servidor Web de produção para depuração.

abafar
fonte
1

Você poderia tentar:

  • iotop (mostrando E / S no sistema)
  • netstat -t (mostrando conexões)
  • Dê uma olhada nos arquivos de log do apache e descubra o que o servidor durou
  • defina alguns RLimits para o processo apache. Quando esses limites são atingidos, o processo será interrompido, fornecendo mais informações
Kai Bojens
fonte
0

Seu comando deve funcionar desde que você faça uma solicitação HTTP que dispara esse PID.

Talvez você queira reconfigurar temporariamente o Apache com apenas um processo filho?

Harry Slaughter
fonte
Lembre-se de que apenas um processo filho significa que o Apache pode atender apenas uma única solicitação e, se esse filho único estiver travado, o Apache não poderá atender a nenhuma solicitação.
Stefan Lasiewski
Não pode fazer isso, pois é um servidor ao vivo com centenas de usuários simultâneos (ter acrescentado que no OP, uma vez que não estava claro antes)
BT643
0

O PID dessa instância do apache é baixo, pode ser o pai de todo o lote. Isso certamente explicaria o alto uso da CPU (ele permanece por perto, outros são gerados e recuperados de acordo com a carga). Muito tempo acumulado da CPU pode significar que ele está em execução há muito tempo. Nenhuma saída strace(1)significa apenas que não houve chamadas do sistema. Sim, pode estar em um loop apertado, mas o apache é essencialmente E / S na rede, então acho que não está fazendo nada útil. Estranho 100% de uma CPU, em qualquer caso.

vonbrand
fonte
PID baixo não significa necessariamente que é um processo antigo. Os PIDs têm um valor máximo e envolvem-se para que novos processos possam ser criados usando PIDs baixos.
de Austin
0

Tente o seguinte:

1) Inicie um log com data / hora, script PHP e PID usando getmypid()

2) Assista ao seu servidor com top

3) Quando o processo apache estiver alto, procure a mesma data / hora e PID em seus logs. Você deve conseguir encontrar o script problemático.

Fénix
fonte
Essa é uma solução interessante, mas vejo que ela consome mais recursos do que vale, já que mod_statusfaz seu trabalho muito bem.
de Austin