gunicornのプロセスが多く見えるときに、二重起動と決めつけない診断手順
gunicornのPIDがいくつも見えても、それだけで二重起動とは言えない。 まずはサービスを止めず、ソケット・親子関係・待機状態・設定値を順番に照合する。
しろまえ殿の現場で、workerらしきプロセスが想定より多く見えた。 さらに、起動スクリプト由来らしいbashも残っていた。
ここで再起動や強制終了に進むと、正常なサービスまで落としかねない。 今回の診断では、read-only(状態を読むだけで変更しない)の確認だけで、異常がないことを組み立てていった。
まず見るのはPIDの数ではなく、つながり
最初に ss -ltnp で、対象ポートのlisten socket(接続を待ち受ける窓口)を確認する。
複数のPIDが同じsocketを参照していれば、masterが開いたファイルディスクリプタをworkerへ引き継いでいる可能性が高い。
ss -ltnp
これは、同じ玄関の鍵を複数の担当者が持っている状態に似ている。 担当者が複数いても、玄関を二つ作ったことにはならない。
本当に別のmasterが同じポートへbind(待ち受け口を割り当てる処理)しようとすれば、後発側は Address already in use で失敗する。
そのエラーがなくサービスが応答しているなら、二重bindを疑う根拠は弱くなる。
次に ps --forest でPPID(親プロセスのPID)を含むツリーを見る。
workerが同じmasterの子として並び、設定したworker数とおおむね対応しているなら、複数PIDはfork(親が子プロセスを作る処理)の結果と説明できる。
ps -eo pid,ppid,stat,cmd --forest
workerの入れ替えが起きる設定では、一時的に世代の異なるPIDが見えることもある。 瞬間の個数だけでなく、親子関係と設定値を一緒に読むことが重要だ。
残ったbashは何を待っているのか
次は、gunicorn本体ではないbashを調べる。
/proc/<pid>/wchan は、カーネル内でそのプロセスが何を待っているかを示す場所だ。
cat /proc/<pid>/wchan
ls -l /proc/<pid>/fd
ps -o pid,ppid,stat,%cpu,rss,cmd -p <pid>
do_wait のような待機状態なら、bashが子プロセスの終了を wait4() で待っているだけかもしれない。
CPU使用率やRSS(プロセスが実メモリ上で使う量)がほぼ増えていなければ、残留しているように見えても直ちに障害とは言えない。
たとえば、受付係が担当者の退勤を待っているだけなのに、受付係まで仕事中の異常者と数えるようなものだ。 待っている対象と待ち方を見れば、見た目の不安を切り分けられる。
今回のbashも、現用masterの終了を待つ古い起動スクリプトの親プロセスだった。 サービスを支えるプロセスではなく、リソース消費も小さいため、強制終了しない判断になった。
「異常なし」を作る四つの照合
同じ状況を調べるときは、次の順序で記録すると判断がぶれにくい。
1. ss -ltnp でlisten socketとPIDの関係を確認する。
2. ps --forest でmasterとworkerの親子関係を確認する。
3. /proc/<pid>/wchan とfd一覧で、残ったプロセスの待機理由と参照先を確認する。
4. gunicornの workers 設定と、実際のworker世代・数を照合する。
各確認は単独の証拠ではない。 しかし、socket共有、同一master配下のworker、終了待ちのbash、設定値との整合がそろえば、二重起動ではないという説明を再現できる。
逆に、別系統のmasterが存在する、別々のsocketを開こうとしている、親子関係が想定外、設定値から大きく外れている、といった差分があれば追加調査へ進む。
見慣れないPIDを見つけたときほど、先に止めるのではなく、何を共有し、誰の子で、何を待っているかを読む。 しろまえ殿の現場でクルーが積み上げたのは、派手な修正ではなく、余計な停止を避けるための地味な診断手順だった。
プロセスが多いことと、プロセスが異常であることは別だ。 事実を一つずつ照合すれば、存在しない障害を追いかけずに済む。