De vez em quando (a cada poucos dias) percebo que um processo está usando 100% da CPU. O processo é avrdude
iniciado pelo Arduino IDE que, em certas circunstâncias que não consegui reproduzir, fica com 100% da CPU, conforme mostrado em top
.
Possivelmente, as circunstâncias são que um upload para a placa Arduino começa e a placa é desconectada durante o processo.
Eu tenho 8 núcleos no processador, então não é imediatamente óbvio que um deles esteja no limite. Na verdade, isso só se torna perceptível se acontecer algumas vezes seguidas, e então eu tenho talvez 3 núcleos com 100% da CPU.
Existe uma maneira de verificar isso em segundo plano (digamos, a cada 15 minutos) e depois me alertar de alguma forma (por exemplo, alguma caixa de diálogo pop-up)? Estou usando o Ubuntu 14.04 LTS.
Agradeço a MelBurslan por sua resposta, mas não sei 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
Reduzi o limite para teste. No entanto, como você pode ver, ele coleta os processos individuais OK, mas o teste final (para exibir a caixa de diálogo) falha porque o pstring ficou vazio repentinamente 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
Responder1
Depois de ler a resposta de MelBurslan e vários comentários, decidi tentar (inspirado nas sugestões deles) fazer uma versão em Lua. Isto foi feito emLua 5.1.5- Não tenho certeza se funcionará com a Lua mais recente.
A idéia geral é usar Lua popen
(abrir um pipe) para executar top
e então processar os dados resultantes usando uma expressão regular (oupadrão, como é chamado em Lua). As linhas correspondentes (que seriam a maioria delas) são então consideradas para ultrapassar a porcentagem limite. Se o fizerem, 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:
- Adicionei um tempo limite de 60 segundos ao zenity para que, se você não estivesse no PC naquele 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 ao executar ocron
. Simplifiquei o teste para "a cada 15 minutos" no crontab, assim:
*/15 * * * * /home/nick/check_cpu_usage.lua
A expressão regular captura tudo,
top
caso você queira fazer outros testes (por exemplo, usando muita memória).
Acho que isso seria mais rápido do que disparar muitos processos e subshells. 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
Responder2
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
em seguida, execute o comando crontab -e
e insira uma linha como esta:
0,15,30,45 * * * * /path/to/my/checker/script
salvar e sair. Então execute
chmod 755 /path/to/my/checker/script
Não estou familiarizado zenity
porque não uso uma exibição gráfica em um servidor Linux há algum tempo e nunca precisei usá-la. Então, se falhar por algum motivo, procure ajuda no man zenity
. É o substituto do executável legado xdialog
, como ouvi.