web-dev-qa-db-ja.com

CPU負荷が最も高いプロセスを自動的に強制終了するにはどうすればよいですか?

プログラムがバックグラウンドでハングアップし、CPU使用率が高くなることがあります。どのプロセスが現時点で最大のCPU負荷を引き起こしているのかをプログラムで確認して強制終了する方法はありますか?

4
Glutanimate

この種の作業に気づいている場合は、おそらくよりよく機能するUnixコマンドのファミリーがあります。

  • pgrep
  • 殺す
  • killall

これらのツールを使用して、特に不正行為のプロセスが名前でわかっている状況で、「攻撃」をより的を絞ったものにすることができます。

killall

Chromeで繰り返し問題が発生し、最終的にはそれをkillして対処する必要があります。通常、このコマンドを実行して、それらすべてを根絶します。

$ 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

それらはARGVがこれらの名前に設定されたBashシェルです。ちなみに、私はこのトリックを使用してそれらのプロセスを作りました:

$ (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

次に、これらをgrep -E ...コマンドに挿入して、特定のプロセスIDに基づいてtopからの出力をフィルター処理できるようにします。

これは多くの逆戻りのように思えるかもしれませんが、使用しているプロセスIDが「weird。* friend」という名前の特定のプロセスに関連するものだけであることが確実にわかりました。

ここから、本当に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                                     

上記は、CPU列(14番目)によってtopからソートされた出力を示しています。それは最低から最高にソートされているので、最後の行(tail -1)を使用します。これは、「weird。* friend」プロセスの最高のCPUプロセスです。

6
slm

プログラム「および」、Auto-Nice Daemonは、その効果に対して何かを実行するように設定できます。

いくつかの特定の既知のトラブルメーカーと3レベルの再ナイス(次第に厳しく再ナイスできるようにする)を使用してリストを設定しますが、そのいずれかは、通常は次のように予約されていますが、プロセスを強制終了する可能性があります最後の手段。

CPU負荷の特定の望ましいレベルを達成するために物事を規制することは必ずしも容易ではありませんが、cpulimitなどの役立つ可能性のある(そして違反を防ぐことにより、問題のあるプロセスの強制終了を回避するのに役立つ)他のツールがあります。ニースとイオニスのプログラム。

3
the dsc

編集済みスクリプト

@ 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の this entry に基づいています。

1
Glutanimate
#!/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
0
sayeed99