如何自动杀死CPU负载最高的进程?

如何自动杀死CPU负载最高的进程?

有时程序会在后台锁定并导致 CPU 使用率过高。有什么方法可以以编程方式确定当前哪个进程导致 CPU 负载最高并杀死它?

答案1

有一系列 Unix 命令,如果您了解它们适合此类工作,它们可能会更好地为您服务。

  • 正则表达式
  • 删除
  • 全杀

您可以使用这些工具使您的“攻击”更有针对性,尤其是在您知道行为不当进程的名称的情况下。

全杀

我的 Chrome 经常出现一个问题,最终需要通过杀死它来解决。我通常会执行此命令来消灭所有它们。

$ killall chrome

pgrep 和 pkill

但我也可以这样做,只处理最新的进程:

# to list
$ pgrep -n chrome
23108

# to kill
$ pkill -n chrome

根据你的命令行进行杀戮

您还可以添加-f开关来访问那些具有您希望匹配的长路径参数的进程,而不仅仅是其可执行文件的名称。

例如,假设我有以下流程:

$ 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

它们只是带有它们的 Bash shellARGV0设置为这些名称。顺便说一句,我使用这个技巧进行了这些过程:

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

去追朋友

但是假设我有很多这样的人,我只想追踪其中的一组特定人,因为他们的命令行中有“朋友”。我可以这样做:

$ pgrep -f friend
26673
26911

追寻最年轻的朋友

如果有几个,而我想选择最新的,请将-n开关添加回组合中:

$ pgrep -fn friend
26911

您还可以在登记-f开关时使用正则表达式,因此这些可以工作,例如:

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

显示他们的名字

您可以使用开关仔细检查进程名称-l

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

控制输出

或者告诉pgrep列出使用逗号 ( ,) 分隔的进程 ID:

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

你可以做这样很酷的事情:

$ 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

那么如何杀死高CPU进程呢?

我会使用上面的内容来更有选择性地追求高 CPU 进程。您可以使用以下方法进行杀死:

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

# kill all of these
$ killall vlc; killall opensnap

看看他们的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 

在这里,我将分隔符从逗号 ( ,) 又名更改为。这个开关-d,,又名管道 ( |)。这个开关-d\|,这样我就可以在grep.这样做将返回进程 ID,如下所示:

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

然后,我们将它们插入到命令中,以便我们可以根据某些进程 IDgrep -E ...过滤输出。top

这看起来似乎有很大的后退,但我们现在可以肯定地知道,我们使用的进程 ID 只是与名为“weird.*friend”的给定进程相关的进程 ID。

从这里你可以找到 CPU 最高的进程并杀死它,如果你真的想这样做的话。

更有针对性的高 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                                     

top上面显示了按 CPU 列排序的输出(第 14 列)。它是从最低到最高排序的,因此我们采用最后一行 ( tail -1),这将是“weird.*friend”进程中 CPU 最高的进程。

答案2

可以设置“和”程序 Auto-Nice Daemon 来执行此操作。

您设置了一个列表,其中包含几个特定的​​已知麻烦制造者和三个重新处理级别(以便您可以逐渐严厉地重新处理),但其中任何一个都可能已经杀死了该进程,尽管这通常会被保留为最后一招。

调节事物以达到特定所需的 CPU 负载水平并不总是那么容易,但还有其他工具可能会有所帮助(并通过防止攻击来帮助避免杀死有问题的进程),例如 cpulimit,并且已经开始带有 Nice 和 ionice 的程序。

答案3

编辑脚本

@msw、@sim 和其他用户对我的脚本的概念提出了合理的担忧。受到 @sim 的回答和 msw 的评论的启发,我坐下来重新思考如何解决我的特定问题(几个已知的进程时不时地造成麻烦)。这是我想出的:

#!/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

与前一个脚本相反,如果 CPU 负载最高的进程的名称与许多已知的麻烦制造者(容易锁定系统的进程)匹配,则该脚本只会杀死该进程。


原创剧本

这是一个简单的脚本,它将确定导致系统上最高瞬时 CPU 负载的进程并杀死它(Xorg 除外,它会导致 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

TOPPROCESS片段基于这个条目在 commandlinefu.com。

答案4

#!/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

相关内容