Como detectar e avisar se um processo está usando 100% da CPU por um longo tempo?

3

De vez em quando (a cada poucos dias), noto que um processo está usando 100% da CPU. O processo é avrdude iniciado pelo IDE do Arduino que, sob certas circunstâncias, eu não consegui reproduzir, fica apenas a 100% da CPU, como mostrado em top .

Possivelmente, as circunstâncias são que um upload para a placa do Arduino começa, e a placa é desconectada durante o processo.

Eu tenho 8 núcleos no processador, por isso não é imediatamente óbvio que um deles está no máximo. Na verdade, isso só se torna perceptível se acontecer algumas vezes seguidas, e então eu tenho talvez 3 núcleos com 100% de CPU.

Existe uma maneira de fazer uma verificação de tarefa em segundo plano (digamos, a cada 15 minutos) e, em seguida, me alertar de alguma forma (por exemplo, alguma caixa de diálogo pop-up)? Estou usando o Ubuntu 14.04 LTS.

Obrigado a MelBurslan por sua resposta, mas não consigo entender por que não está funcionando totalmente. Meu script atual é este:

cpupercentthreshold=2
pstring=""
top -b -n 1 | sed -e "1,7d" | while read line; do
cpuutil=$(echo ${line} | awk '{print $9}' | cut -d"." -f 1)
procname=$(echo ${line} | awk '{print $12}' )
if [ ${cpuutil} -ge ${cpupercentthreshold} ]
then
  echo ${cpuutil}
  pstring=${pstring}${procname}" "
  echo pstring is currently ${pstring}
fi
done
echo pstring is ${pstring}
if [ -n "${pstring}" ]
then
  zenity --title="Warning!" --question --text="These processes are above CPU threshold limit ${pstring}" --ok-label="OK"
fi

Eu reduzi o limite para testes. No entanto, como você pode ver, ele coleta os processos individuais em OK, mas o teste final (para exibir a caixa de diálogo) falha porque a pstring ficou vazia de repente por motivos que não consigo ver:

13
pstring is currently VirtualBox
6
pstring is currently VirtualBox Xorg
6
pstring is currently VirtualBox Xorg compiz
6
pstring is currently VirtualBox Xorg compiz ibus-engin+
6
pstring is currently VirtualBox Xorg compiz ibus-engin+ top
pstring is
    
por Nick Gammon 16.02.2016 / 21:56

2 respostas

1

Depois de ler a resposta de MelBurslan e vários comentários, decidi tentar (inspirado em suas sugestões) fazer uma versão em Lua. Isso foi feito em Lua 5.1.5 - Não tenho certeza se ele funcionará com a Lua mais recente.

A ideia geral é usar popen (open a pipe) de Lua para executar top e então processar os dados resultantes usando uma expressão regular (ou padrão , como é chamado em Lua ). Linhas correspondentes (que seriam a maioria delas) são então consideradas para cruzar a porcentagem limite. Se eles fizerem isso, eles serão adicionados a uma tabela.

Se a tabela não estiver vazia, então zenity é chamado para exibir uma mensagem ao usuário. Algumas "pegadinhas" que encontrei durante o desenvolvimento:

  • Eu adicionei um tempo limite de 60 segundos ao zenity para que, se você não estivesse no PC no momento, não preenchesse a tela com caixas de diálogo de aviso.
  • Eu adicionei --display=:0.0 para que uma tela de exibição fosse encontrada durante a execução em cron .
  • Eu simplifiquei o teste para "a cada 15 minutos" no crontab, assim:

    */15 * * * * /home/nick/check_cpu_usage.lua
    
  • A expressão regular captura tudo de top caso você queira fazer outros testes (por exemplo, usar muita memória).

Acho que isso seria mais rápido do que disparar muitos processos e subpastas. Parece funcionar bem. Teste reduzindo o limite (por exemplo, para 5) e altere a entrada do crontab para verificar a cada minuto.

check_cpu_usage.lua

#! /usr/local/bin/lua

THRESHOLD = 90  -- percent

-- pipe output of top through a file "f"
f = assert (io.popen ("top -b -n 1 -w 512"))
t = { }

-- check each line
for line in f:lines() do

  -- match top output, eg.
  --   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  -- 30734 nick      20   0 6233848 3.833g 3.731g S   8.6 12.2   3:11.75 VirtualBox

  local pid, user, priority, nice, virt, res, shr, 
        status, cpu, mem, time, command =
    string.match (line,
      "^%s*(%d+)%s+(%a+)%s+(%-?%d+)%s+(%-?%d+)" ..
--         pid      user   priority    nice
      "%s+([%d.]+[g]?)%s+([%d.]+[g]?)%s+([%d.]+[g]?)%s+([DRSTZ])%s+(%d+%.%d+)%s+(%d+%.%d+)" ..
--        virtual          res           shr             status       %cpu        %mem
      "%s+([0-9:.]+)%s+(.*)$")
--         time       command

  -- if a match (first few lines won't) check for CPU threshold
  if pid then
    cpu = tonumber (cpu)
    if cpu >= THRESHOLD then
      table.insert (t, string.format ("%s (%.1f%%)", command, cpu))
    end -- if
  end -- if

end -- for loop

f:close()

-- if any over the limit, alert us
if #t > 0 then
  os.execute ('zenity --title="CPU usage warning!" --info ' ..
              '--text="These processes are using more than ' ..
              THRESHOLD .. '% CPU:\n' ..
              table.concat (t, ", ") ..
              '" --ok-label="OK" ' ..
              '--timeout=60 ' ..   -- close dialog after one minute in case we aren't around
              '--display=:0.0 '  -- ensure visible when running under cron
              )
end -- if
    
por 17.02.2016 / 05:48
0

crie um script simples como este

cpupercentthreshold=75
pstring=""
top -b -n 1 | sed -e "1,7d" | while read line; do
cpuutil=$(echo ${line} | awk '{print $9}' | cut -d"." -f 1)
if [ ${cpuutil} -ge ${cpupercentthreshold} ]
then
  pstring=${pstring}${procname}" "
fi
done
if [ -z "${pstring}" ]
then
  echo "Everything looks good $(date)" >>mylogfile #if you want to keep track 
else
  zenity --title="Warning!" --question --text="These processes are above CPU threshold limit ${pstring}" --ok-label="OK"
fi

execute o comando crontab -e e insira uma linha como esta:

0,15,30,45 * * * * /path/to/my/checker/script 

salve e saia. Então execute

chmod 755 /path/to/my/checker/script

Eu não estou familiarizado com zenity , pois não utilizei uma exibição gráfica em um servidor linux por um tempo e nunca precisei usá-la. Portanto, se falhar por algum motivo, procure ajuda em man zenity . É o substituto do executável legado xdialog , como eu ouvi.

    
por 16.02.2016 / 22:45