CPUやメモリの使用率が80%に達した場合にプロセスを強制終了するスクリプトを作成しました。これが発生すると、強制終了されたプロセスのリストが作成されます。それを改善するために私は何ができますか?
while [ 1 ];
do
echo
echo checking for run-away process ...
CPU_USAGE=$(uptime | cut -d"," -f4 | cut -d":" -f2 | cut -d" " -f2 | sed -e "s/\.//g")
CPU_USAGE_THRESHOLD=800
PROCESS=$(ps aux r)
TOPPROCESS=$(ps -eo pid -eo pcpu -eo command | sort -k 2 -r | grep -v PID | head -n 1)
if [ $CPU_USAGE -gt $CPU_USAGE_THRESHOLD] ; then
kill -9 $(ps -eo pid | sort -k 1 -r | grep -v PID | head -n 1) #original
kill -9 $(ps -eo pcpu | sort -k 1 -r | grep -v %CPU | head -n 1)
kill -9 $TOPPROCESS
echo system overloading!
echo Top-most process killed $TOPPROCESS
echo CPU USAGE is at $CPU_LOAD
else
fi
exit 0
sleep 1;
done
私は推測解決したい問題は、ボックスで実行中のプロセスが時々誤動作し、永久にコアをペギングしていることです。
最初にしたいことは、狂ったプログラムを修正することです。それは断然最良の解決策です。私はそれが不可能であると仮定します。そうしないと、箱が修理されるまで箱を動かし続けるためのクイッククルージが必要です。
少なくとも、問題のある1つのプログラムのみにヒットするようにスクリプトを制限したいとします。権限によってこのようにスクリプトが制限された場合に最適です(たとえば、スクリプトはユーザーXとして実行され、Xとして実行される他の唯一のものはプログラムです)。
_ulimit -t
_のようなものを使用して、プログラムが使用できる合計CPU時間を制限することをお勧めします。同様に、すべてのメモリを消費する場合は、_ulimit -v
_を確認します。カーネルはこれらの制限を強制します。詳細については、bash
マンページ(シェル組み込み)とsetrlimit(2)
マンページを参照してください。
問題がamokを実行しているプロセスではなく、実行しているプロセスが多すぎる場合は、何らかの形式のロックを実装して、X以上が実行されないようにします(または、これは慣れ親しんでいるはずです_ulimit -u
_)。また、これらのプロセスのスケジューラの優先度を変更することを検討することもできます(Nice
またはrenice
を使用)。または、より徹底的に、_sched_setscheduler
_を使用してポリシーを_SCHED_IDLE
_に変更することもできます。 。
さらに制御が必要な場合は、制御グループ(cgroups)を見てください。実行しているカーネルに応じて、プロセスのグループ全体が一緒に消費するCPU時間、メモリ、I/Oなどの量を実際に制限できます。コントロールグループは非常に柔軟です。壊れやすいクルージがなくても、あなたがしようとしていることは何でもできるでしょう。 Arch Linux Wikiには cgroupsの紹介 があり、LWNには Neil Brownのcgroupsシリーズ があるので一読に値します。
問題:
-n
オプションを使用することをお勧めします:sort -nrk 2
。そうしないと、%CPU
の値が5.0の行は、値が12.0の行よりも高くなります。ps
の実装によっては、--no-headers
オプションを使用してgrep -v
を削除することもできます。これにより、PID
を含むコマンドを破棄できなくなります。echo CPU USAGE is at $CPU_LOAD
ではなく、echo CPU USAGE is at $CPU_USAGE
を意味しているようです。exit 0
を削除するのを忘れたようです(?)。スタイル:
CPU_USAGE_THRESHOLD=800
行をファイルの先頭に移動することをお勧めします。これは、最も情報量が多く、スクリプトが安定した後でも変更される可能性が最も高いためです。-e
オプションを繰り返しています。ps -eo pid -eo pcpu -eo command
はps -eo pid -o pcpu -o command
と同じです(ps -eo pid,pcpu,command
も同様)。else
句があります。これは常に処理する必要があるかのように見えますが、何らかの理由でそうではありませんでした。ほとんどのCPU /メモリを使用しているプロセスを強制終了すると、問題が発生します。マシンの現在の状態を確認してください(ここでは現在、firefox、systemd(init)、Xorg、gnome-terminal、カーネルスレッドのセット、xemacs、どれも必須ではありません)。 LinuxのOOM-killerを調整する方法を見てください(例 here )。
また、「プロセスが使用するメモリ」は曖昧な概念であることに注意してください。共有ライブラリ、実行可能ファイル、さらにはデータ領域の一部さえ存在するからです。各ユーザーに使用済みスペースのごく一部を請求することでいくつかの数字を思い付くことができますが、それを追加しても実際には「使用メモリ」は得られません(プロセスがなくなると「メモリ解放」が少なくなります)。後ろに)。
CPU使用率がYY秒間XX%を超える場合、またはZZ秒を超えて実行されているプロセスを強制終了する場合、配列にリストされた一部のプロセスを強制終了するスクリプト kill-process を作成しました。
注:これがGithub上の私のリポジトリです: https://github.com/padosoft/kill-process
これがスクリーンショットです:
#!/usr/bin/env bash
#max cpu % load
MAX_CPU=90
#max execution time for CPU percentage > MAX_CPU (in seconds 7200s=2h)
MAX_SEC=1800
#sort by cpu
SORTBY=9
#define a processes command name to check
declare -a KILLLIST
KILLLIST=("/usr/sbin/Apache2" "/usr/bin/php5-cgi")
#iterate for each process to check in list
for PROCESS_TOCHECK in ${KILLLIST[*]}
do
#retrive pid with top command order by SORTBY
PID=$(top -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $1}')
CPU=$(top -p $PID -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $9}')
TIME_STR=$(top -p $PID -bcSH -n 1 | grep $PROCESS_TOCHECK | sort -k $SORTBY -r | head -n 1 | awk '{print $11}')
# Decode the top CPU time format [dd-]hh:mm.ss.
TIME_SEC=0
IFS="-:" read c1 c2 c3 c4 <<< "$TIME_STR"
#with top command time format is hh:mm.ss, so truncare seconds in c2
c2=${c2%%.*}
if [ -n "$c4" ]
then
TIME_SEC=$((10#$c4+60*(10#$c3+60*(10#$c2+24*10#$c1))))
Elif [ -n "$c3" ]
then
if [ "$CMD" = "ps" ]; then
TIME_SEC=$((10#$c3+60*(10#$c2+60*10#$c1)))
else
TIME_SEC=$(((10#$c3*24)*60*60)+60*(10#$c2+60*10#$c1))
fi
else
if [ "$CMD" = "ps" ]; then
TIME_SEC=$((10#0+(10#$c2+60*10#$c1)))
else
TIME_SEC=$((10#0+60*(10#$c2+60*10#$c1)))
fi
fi
#check if need to kill process
if [ $CPU -gt $MAX_CPU ] && [ $TIME_SEC -gt $MAX_SEC ]; then
kill -15 $PID
fi
done
bash killprocess.sh [dry|kill|--help] [top|ps] [cpu|time]