Como posso matar automaticamente o processo com a maior carga de CPU?

3

Às vezes, os programas ficam bloqueados em segundo plano e causam alto uso da CPU. Existe alguma maneira que eu possa verificar programaticamente qual processo está causando a maior carga da CPU no momento e matá-lo?

    
por Glutanimate 11.09.2013 / 02:46

4 respostas

5

Há uma família de comandos do Unix que provavelmente irá atendê-lo melhor se você estiver ciente deles para esse tipo de trabalho.

  • pgrep
  • pkill
  • killall

Você pode usar essas ferramentas para tornar seus "ataques" mais direcionados, especialmente em situações em que você conhece o processo de mau comportamento por nome (s).

killall

Eu tenho um problema recorrente com o Chrome, no qual, eventualmente, ele precisa ser resolvido, eliminando-o. Eu costumo fazer este comando para erradicar todos eles.

$ killall chrome

pgrep & pkill

Mas eu também poderia fazer isso para lidar apenas com o processo mais recente:

# to list
$ pgrep -n chrome
23108

# to kill
$ pkill -n chrome

Matança baseada em sua linha de comando

Você também pode adicionar a opção -f para alcançar os processos que possuem argumentos de caminho longo com os quais você preferiria corresponder, em vez de apenas o nome do executável.

Por exemplo, digamos que eu tenha esses processos:

$ ps -eaf | grep some
saml     26624 26575  0 22:51 pts/44   00:00:00 some weird command
saml     26673 26624  0 22:51 pts/44   00:00:00 some weird command's friend
saml     26911 26673  8 22:54 pts/44   00:00:00 some weird command's friend

Eles são apenas shells Bash com o seu ARGV0 definido para esses nomes. Aliás, eu fiz esses processos usando esse truque:

$ (exec -a "some weird command name's friend" bash)

Indo atrás dos amigos

Mas digamos que eu tenha muitos deles, e eu só quero ir atrás de um grupo específico deles porque eles têm "amigos" em suas linhas de comando. Eu poderia fazer isso:

$ pgrep -f friend
26673
26911

Indo depois do amigo mais novo

E se houvesse alguns deles e eu quisesse ir atrás do mais novo, adicione o -n de volta ao mix:

$ pgrep -fn friend
26911

Você também pode usar expressões regulares ao inscrever a opção -f , para que elas funcionem, por exemplo:

$ pgrep -f "weird.*friend"
26673
26911

Exibindo seus nomes

Você pode verificar os nomes dos processos usando a opção -l :

$ pgrep -f "weird.*friend" -l
26673 some weird command's friend
26911 some weird command's friend

Controlando a saída

Ou informe pgrep para listar os IDs de processo delimitados usando uma vírgula ( , ):

$ pgrep -f "weird.*friend" -d,
26673,26911

Você pode fazer coisas legais como esta:

$ ps -fp $(pgrep -f weird -d,)
UID        PID  PPID  C STIME TTY          TIME CMD
saml     26624 26575  0 22:51 pts/44   00:00:00 some weird command
saml     26673 26624  0 22:51 pts/44   00:00:00 some weird command's friend
saml     26911 26673  0 22:54 pts/44   00:00:00 some weird command's friend

Então, como eu mato o processo de alta CPU?

Eu usaria o acima para ser mais seletivo ao ir atrás de um processo de CPU alto. Você poderia usar a abordagem de matar usando esses métodos:

# newest guys
$ pkill -nf vlc ; pkill -nf opensnap

# kill all of these
$ killall vlc; killall opensnap

Veja as cargas da CPU:

$ top -b -n 1 | grep -E $(pgrep -f "weird.*friend" -d\|) | grep -v grep
26911  0.1  112m 106m 6408  848 4900 1512    0    0 S  20   0  0.0 some weird command's friend                                     
26673  0.1  112m 106m 6392  848 5020 1504    0    0 S  20   0  0.0 some weird command's friend 

Aqui eu mudei o delimitador de uma vírgula ( , ) aka. este comutador -d, , para um pipe ( | ) aka. essa opção -d\| , para que eu possa usá-la em grep . Fazendo isso, os IDs do processo serão retornados assim:

$ pgrep -f "weird.*friend" -d\|
26673|26911

Em seguida, os inserimos no comando grep -E ... para que possamos filtrar a saída de top com base em determinadas IDs de processo.

Isso pode parecer muito difícil, mas agora sabemos com certeza que os IDs de processo que estamos usando são apenas aqueles relacionados a um processo de criação denominado "estranho. * amigo".

A partir daqui, você pode encontrar o processo com a maior CPU e eliminá-lo, se você realmente quiser seguir esse caminho.

Uma abordagem mais direcionada à alta CPU

$ top -b -n 1 | grep -E $(pgrep -f "weird.*friend" -d\|) | \
    grep -v grep | sort -nk14,14 | tail -1
26911  0.1  112m 106m 6408  848 4900 1512    0    0 S  20   0  0.0 some weird command's friend                                     

O exemplo acima mostra a saída ordenada de top pela coluna da CPU (14ª). É classificado do menor para o maior, então pegamos a última linha ( tail -1 ) que seria o processo de CPU mais alto dos processos "estranho. * Amigo".

    
por 11.09.2013 / 05:35
3

O programa "e", o Auto-Nice Daemon pode ser configurado para fazer algo nesse sentido.

Você configurou uma lista com vários criadores de problemas conhecidos e três níveis de refinamento (para que você possa voltar a agradar progressivamente), mas qualquer um poderia ser o mesmo que matar o processo, mesmo que isso fosse mais comum ser reservado como último recurso.

Nem sempre é fácil regular as coisas para que você atinja determinados níveis desejados de carga da CPU, mas existem outras ferramentas que podem ajudar (e ajudar a evitar a morte do processo de ataque, impedindo a ofensa), como cpulimit, e já iniciando programas com nice e ionice.

    
por 16.09.2016 / 15:04
0

Script editado

@msw, @sim e outros usuários levantaram preocupações válidas quanto ao conceito do meu script. Inspirado pela resposta de @ sim e pelos comentários de msw, sentei-me e repensadamente como resolver meu problema em particular (alguns processos conhecidos causando problemas de vez em quando). Aqui está o que eu criei:

#!/bin/bash

# tries to kill process with highest CPU load
# (if it is part of a specified list of troublemakers)

TROUBLEMAKERS="vlc opensnap glxgears stress"


sleep 1 # wait a few seconds (just as a precaution)

TOPPROCESS=$(top -b -n 1 | sed 1,6d | sed -n 2p)
TOPPID=$(echo "$TOPPROCESS" | awk '{print $1}')
TOPNAME=$(echo "$TOPPROCESS" | awk '{print $12}')

if [[ "$TROUBLEMAKERS" == *"$TOPNAME"* ]]
  then
      echo "Cause of high CPU load: "$TOPNAME" ("$TOPPID")"
      echo "In troublemaker list. Killing..."
      kill -9 $TOPPID
  else
      echo "Cause of high CPU load: "$TOPNAME" ("$TOPPID")"
      echo "Not in troublemaker list. Exiting..."
      exit 1
fi

exit 0

Em contraste com o script anterior, este apenas matará o processo com a maior carga de CPU se o seu nome corresponder a um número de criadores de problema conhecidos (processos que tendem a bloquear em seu sistema).

Roteiro original

Aqui está um script simples que determinará o processo causando o maior carregamento momentâneo de CPU no sistema e o matará (com exceção do Xorg, o que causaria a falha da GUI):

#!/bin/bash

# tries to kill process with highest CPU load
# (if it isn't Xorg)

sleep 1 # wait a few seconds (just as a precaution)

TOPPROCESS=$(top -b -n 1 | sed 1,6d | sed -n 2p)
TOPPID=$(echo "$TOPPROCESS" | awk '{print $1}')
TOPNAME=$(echo "$TOPPROCESS" | awk '{print $12}')

if [ "$TOPNAME" != "Xorg" ]
  then
      kill -9 $TOPPID
  else
      echo "CPU load caused by Xorg. Exiting."
      exit 1
fi

exit 0

O TOPPROCESS snippet é baseado em esta entrada no commandlinefu. com.

    
por 11.09.2013 / 02:46
0
#!/bin/bash
pid=$(ps -eo %cpu,pid --sort -%cpu | head -n 2 | awk '{print $1 " " $2}')
if [[ -n $pid ]]; then
    kcpu=$(echo $pid | awk '{print $3}')
    kpid=$(echo $pid | awk '{print $4}')
    ift=$(echo "90"'<'$kcpu | bc -l)
    if [ $ift -eq "0" ]; then
        echo "kpid = $kpid"
        kill $kpid
    fi
else
echo "Does not exist"
fi
    
por 10.08.2017 / 20:26