きっかけ
以前にAWS SSMを通じて、別サーバからDBを参照できるようにしていました。
そしたらバックグラウンド(nohup)実行のタスクが、ゾンビとして大量に生産され大変なことになっていました...
こんな感じ
[hoge@hogehost ~]$ ps -ef | grep defunct
root 338 334 0 6月30 ? 00:00:00 [sh] <defunct>
root 3127 3126 0 6月30 ? 00:00:00 [sh] <defunct>
root 5791 5789 0 6月30 ? 00:00:00 [sh] <defunct>
root 8468 8466 0 6月30 ? 00:00:00 [sh] <defunct>
root 11150 11146 0 6月30 ? 00:00:00 [sh] <defunct>
# 以下略 #
defunctとは?
ゾンビプロセス確認には、ps -ef | grep defunct
で検索したけどdefunct
ってなんぞやと思いました。
上記から、
- プロセスのタスク完了/破損/キルのいずれかの状態
- だけど、子プロセスとして実行されている
- もしくは、親プロセスは、該当する子プロセスを監視している
ということを示していることがわかりました。
また、プロセスIDの削除についても親と子の両方のプロセスを殺す必要がわかりました。
kill -9 PID1 PID2
やったこと
- ゾンビプロセスの自動キル
- 一応30分ごとに張るセッションを切らないように、1時間経過したゾンビだけを削除
- 月から金まで、6時間ごとに一括削除
cron
* */6 * * 1-5 ./kill_zombie_process.sh;
zombie_process_kill.sh
#/bin/bash
# REF: https://ex1.m-yabe.com/archives/3490
PName=defunct
PID=$$
for i in `ps -ef | grep $PName | grep -v $PID | grep -v grep | awk '{print $2,$3}'`
do
TIME=`ps -o lstart --noheader -p $i`
if [ -n "$TIME" ]; then
StartupTime=`date +%s -d "$TIME"`
CurrentTime=`date +%s`
ElapsedTime=`expr $CurrentTime - $StartupTime`
else
ElapsedTime=1
fi
# 1時間以上経過したゾンビプロセスは削除する
if [ $ElapsedTime -gt 3600 ] ; then
kill -9 $i
fi
done
参考