状況
japanクラスターにjapan{01..10}.jpy.netという名の10つのノードが存在するとする。
mpd.pyというプログラムが正常終了せずに実行可能状態のまま残ってしまうとき、演算能力が著しく低下することがわかった。
そのため、以下のスクリプトを定期実行することで解決した。
コード
#!/bin/sh
NAME=`hostname`
HOST=`echo $NAME|rev|cut -c 11-|rev`
echo "## hostname ##"
echo $HOST
echo " "
NODES=(`cat /etc/hosts|grep $HOST|awk '{print $2}'|rev|cut -c 9-|rev|grep $HOST`)
echo "Kill mpd.py !!!"
for j in ${NODES[@]}
do
echo " "
echo " "
echo "## $j ##"
cnt=`/usr/bin/rsh $j ps aux --sort start_time |grep mpd.py|wc -l`
echo "jobcount $cnt"
cpucnt=`/usr/bin/rsh $j grep processor /proc/cpuinfo | wc -l`
echo "nodecpus $cpucnt"
jobremain=`expr $cpucnt + $cpucnt`
echo "jobremain count $jobremain"
jobkillcnt=`expr $cnt - $jobremain`
echo "killjob count $jobkillcnt"
if [ $jobkillcnt -le 0 ]; then
echo "no remaining processes"
continue
fi
killjoblist=(`/usr/bin/rsh $j ps aux --sort start_time|grep mpd.py|awk '{print $2}'|head -n $jobkillcnt`)
flag=(`/usr/bin/rsh $j ps auxf --sort start_time|grep mpd.py|grep -v grep|head -n $jobkillcnt|fgrep "\_"`)
if [ -n "$flag" ]; then
echo "Exist child processes"
continue
fi
killcnt2=`expr $jobkillcnt + 1`
flag2=(`/usr/bin/rsh $j ps auxf --sort start_time|grep mpd.py|grep -v grep|head -n $killcnt2|tail -n 1|fgrep "\_"`)
if [ -n "$flag2" ]; then
echo "Exist child processes"
continue
fi
for i in "${killjoblist[@]}"
do
chk=`/usr/bin/rsh $j ps aux|grep mpd.py |grep $i`
if [ -z "$chk" ]; then
continue
fi
/usr/bin/rsh $j kill $i
done
wait
#TCPポート枯渇対策
sleep 1m
done
コード解説
例外処理
killjoblist=(`/usr/bin/rsh $j ps aux --sort start_time|grep mpd.py|awk '{print $2}'|head -n $jobkillcnt`)
flag=(`/usr/bin/rsh $j ps auxf --sort start_time|grep mpd.py|grep -v grep|head -n $jobkillcnt|fgrep "\_"`)
killjoblistはその名の通りkillする予定のPID配列です。flagは例外処理で消すリストの中に子プロセスが存在したらskipするようにしてあります。flag2は消すリストの最後尾が親プロセスで子が隠れているコーナーケースを考えた処理です。
TCPポート枯渇対策
slepp 1m
これをつけないとAll port usedみたいなエラーを吐いて異常終了します。1mの意味はCentOSではデフォルトのTCPのタイムアウト時間が1mだからです。
xargsを使ってkillするほうが楽かもしれないけど、rootでkillコマンドをスクリプトで実行する危険性を考えると、本当に消してもよいか丁寧にチェックしたいので用いませんでした。その他もっと良い書き方がありましたらコメントで教えてください。
定期実行したい
rootのcrontabに以下を追記してやればよい。日曜日と木曜日の午前0時に実行する設定
0 0 * * 0,4 /usr/local/bin/mpdestroy 2>> /var/log/mpdestory_log/log_mpdestory_error_$(date +\%Y\%m\%d).log