¿Cómo detectar y avisar si un proceso está usando el 100% de la CPU durante mucho tiempo?

¿Cómo detectar y avisar si un proceso está usando el 100% de la CPU durante mucho tiempo?

De vez en cuando (cada pocos días) noto que un proceso utiliza el 100% de la CPU. El proceso lo avrdudeinicia el IDE de Arduino que, bajo ciertas circunstancias que no he podido reproducir, simplemente permanece allí al 100% de la CPU, como se muestra en top.

Posiblemente las circunstancias sean que comience una carga en la placa Arduino y la placa se desconecte durante el proceso.

Tengo 8 núcleos en el procesador, por lo que no es inmediatamente obvio que uno de ellos esté al máximo. De hecho, solo se nota si sucede varias veces seguidas, y luego tengo quizás 3 núcleos al 100% de CPU.

¿Hay alguna manera de realizar alguna verificación de tareas en segundo plano para esto (digamos, cada 15 minutos) y luego alertarme de alguna manera (por ejemplo, algún cuadro de diálogo emergente)? Estoy usando Ubuntu 14.04 LTS.


Gracias a MelBurslan por su respuesta, pero no sé por qué no funciona del todo. Mi script actual es 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

Bajé el umbral para realizar pruebas. Sin embargo, como puede ver, recopila los procesos individuales correctamente, pero la prueba final (para mostrar el cuadro de diálogo) falla porque pstring de repente quedó vacío por razones que no puedo 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

Respuesta1

Después de leer la respuesta de MelBurslan y varios comentarios, decidí intentar (inspirado por sus sugerencias) hacer una versión en Lua. Esto se hizo enLua 5.1.5- No estoy seguro de si funcionará con la última versión de Lua.

La idea general es usar Lua popen(abrir una tubería) para ejecutar topy luego procesar los datos resultantes usando una expresión regular (opatrón, como se llama en Lua). Luego se consideran las líneas coincidentes (que serían la mayoría de ellas) para cruzar el porcentaje umbral. Si lo hacen, se agregan a una tabla.

Si la tabla no está vacía, zenityse llama para mostrar un mensaje al usuario. Algunos "errores" que encontré durante el desarrollo:

  • Agregué un tiempo de espera de 60 segundos a zenity para que, si no estaba en la PC en ese momento, no llenara la pantalla con cuadros de diálogo de advertencia.
  • Agregué --display=:0.0para que se encontrara una pantalla de visualización cuando se ejecutaba en cron.
  • Simplifiqué la prueba "cada 15 minutos" en el crontab, así:

    */15 * * * * /home/nick/check_cpu_usage.lua
    
  • La expresión regular captura todo topen caso de que desee realizar otras pruebas (por ejemplo, usar demasiada memoria).

Creo que esto sería más rápido que iniciar muchos procesos y subcapas. Parece funcionar bien. Pruebe reduciendo el umbral (por ejemplo, a 5) y cambie la entrada de crontab para verificar cada minutos.


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

Respuesta2

crea un script simple 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

luego ejecute el comando crontab -ee inserte una línea como esta:

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

guardar y Salir. Luego ejecuta

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

No lo conozco zenityporque no he usado una pantalla gráfica en un servidor Linux por un tiempo y nunca necesité usarla. Entonces, si falla por algún motivo, busque ayuda en man zenity. Es el reemplazo del ejecutable heredado xdialog, según escuché.

información relacionada