- サーバー
- 技術 💻
Linuxの怪現象8選|rmしても減らない・ゾンビ・kill
Linuxサーバーの怪現象って、だいたいパターンが決まっているんですよね。
消したのに減らない。killしても死なない。SSHを切ったらジョブごと消えた。全部、プロセスとファイルの仕組みが説明してくれます。今回は、運用で必ず出会うものを8つ集めました。1つでも知らなかったら儲けものです。
① rmしたのに、ディスクが減りません
ディスク逼迫時の定番、巨大ログの削除。
$ rm huge.log # 10GBを削除
$ df -h # → 空き容量、変わらず!?
原因は、プロセスがそのファイルを開いたままだからです。rmが消すのは「名前」だけで、実体は開いている全プロセスが手放すまで残ります。
犯人は lsof +L1(削除済みなのに開かれているファイル一覧)で見つかります。
- 消す前なら:ファイルを消すのではなく、中身を空にする(
> huge.log) - もう消してしまったら:lsofで分かったプロセスID(PID)とfd番号を使い、
: > /proc/<PID>/fd/<番号>で中身を空にする。またはそのプロセスを再起動する
「削除=名前を外すこと」——このモデルが頭に入ると、この謎は二度と謎じゃなくなります。
② ゾンビプロセスは、killできません
プロセス一覧に残り続ける <defunct>、ゾンビプロセスです。
kill -9 を打っても消えません。なぜなら、ゾンビはもう死んでいるからです。
ゾンビの正体は、終了済みだが、親プロセスが終了報告(終了コード)をまだ受け取っていない状態。報告書だけが机に残っている、と思ってください。
だから消す方法は、ゾンビ本人ではなく親に報告を受け取らせること。親が回収しないバグなら、親を再起動(または終了)すれば、ゾンビはOSの初代プロセス(PID 1)に引き取られて回収されます。撃つ相手は、親なんです。
③ forkは、メモリを全コピーしません
プロセスの複製(fork)は、親のメモリを丸ごとコピーする——建前上は。
実際は、コピーオンライト(CoW)という仕組みで、その瞬間は何もコピーしません。親子でメモリを共有し、どちらかが書き込んだページだけ、その時に初めて複製します。
だから数GBのメモリを使うプロセスでも、forkは一瞬で終わる。
「巨大プロセスからforkした瞬間にメモリが倍になるのでは」という心配が(基本的には)要らないのは、この遅延コピーのおかげなんです。
④ 「Too many open files」の正体は、番号札の枯渇です
Linuxでは、ファイルもソケットもパイプも、ぜんぶ「ファイルディスクリプタ(fd)」という番号札で扱われます。「すべてはファイル」という設計思想です。
そしてこの番号札には、プロセスごとの上限があります(既定は1024のことが多い)。
つまり「Too many open files」は、ファイルの開きすぎとは限りません。閉じ忘れたソケットや接続リークでも起きます。Webサーバーで頻出するのはむしろこちら。
ls /proc/<PID>/fd で、いま掴んでいる番号札が全部見えます。エラー名に騙されず、fdの中身を見るんです。
⑤ kill -9 でも死なないプロセスが、実在します
SIGKILLは最強の必殺技——のはずが、効かない相手がいます。
「D」状態(割り込み不能スリープ)のプロセスです。ディスクやNFSの応答を待つカーネル内の処理中で、その待ちが終わるまで、シグナルが届きません。
NFSサーバーが応答しなくなったとき、lsコマンドすらD状態で固まって殺せない——運用者なら一度は見る光景です。
D状態が大量発生していたら、犯人はプロセスではなくその下のI/O(ストレージやネットワークファイルシステム)。見る場所が一段下がるんです。
⑥ SSHを切ると、ジョブが死ぬ理由
長時間バッチをSSH越しに実行して、接続が切れたらバッチも死んだ——新人期の通過儀礼です。
理由は、端末が切れると、その端末のプロセスたちにSIGHUP(切断通知)が送られるから。既定の反応は「終了」です。対策は用途で選びます。
| 方法 | 向いている用途 |
|---|---|
nohup | SIGHUPを無視させる最小手段 |
tmux / screen | 端末ごと生かしておき、後で再接続したいとき |
| systemdなどのサービス登録 | 恒久的に動かし続けるジョブ(本筋) |
「&を付けたのに死んだ」のは、バックグラウンド化とSIGHUP対策が別の話だからなんです。
⑦ 環境変数は、「起動時のコピー」です
exportしたのに、動いているアプリに反映されない——仕様です。
環境変数は、プロセスが起動する瞬間に、親から子へコピーされるものです。起動後に親のシェルでexportしても、既に動いているプロセスには届きません。逆方向(子が変更して親に反映)は、そもそも不可能です。
「設定を変えたのに効かない」の一定数は、これ。反映には再起動が要る、が原則です。
環境変数は「共有される設定」ではなく「出生時に持たされた荷物」。このモデルで、挙動が全部読めます。
⑧ メモリが尽きると、OSがプロセスを「選んで」殺します
最後は、突然死の裏側です。
Linuxはメモリが本当に枯渇すると、OOM Killerという仕組みが、スコアの高いプロセスを選んで強制終了します。アプリのログには何も残らず、忽然と消える。
「アプリが落ちた形跡がないのに死んでいる」ときは、アプリのログではなくOS側のログ(dmesgやjournal)を見る。「Out of memory: Killed process ...」の1行が答えです。
誰が殺されやすいかはスコアで調整もできます。巻き添えで大事なプロセスが死なない設計まで含めて、メモリ管理なんです。
番外編:手元で確かめられる小ネタ
/proc は、カーネルの窓です
/proc/<PID>/ の下には、そのプロセスのfd、環境変数、メモリマップが「ファイルのふり」をして並んでいます。④⑦の話は、ここを覗けば全部実物が見えます。
killは「殺すコマンド」ではありません
killの正体はシグナル送信コマンドです。kill -USR1 で再読込、kill -STOP で一時停止——殺す以外の用途がたくさんあるんです。
プロセスの家系図を見る
ps -ef --forest
親子関係がツリーで出ます。②の「親は誰か」も、⑥の「どの端末の子か」も、この1枚で見えます。
RJCでも、Linuxと向き合っています
RJCが携わるシステムの本番は、Linuxサーバーの上で長時間動き続ける世界です。①や⑧のような「知っていれば5分、知らなければ半日」の知識は、そのまま障害対応力なんですよね。
こういう仕組みの話を、Techチームで共有しながら開発しています。
よくいただくご質問
Q. まずどれから押さえるべきですか?
A. ①かなと思います。ディスク逼迫は緊急対応になりがちなので、「> で切り詰める」を知っているだけで初動が変わるんですよね。
Q. コマンドを覚えるコツはありますか?
A. コマンドより先に「プロセス・fd・シグナル」の3つのモデルを絵にすることをおすすめします。コマンドは全部、その絵の操作なんです。
Q. 障害時にまず何を見ればいいですか?
A. ps(プロセスの状態)、lsof/fd(何を掴んでいるか)、dmesg(OSが何をしたか)の3点セットです。今日の①④⑤⑧が、ほぼこの3つで切り分けられます。
Q. 未経験からでも、分かるようになりますか?
A. なります。Linuxは仕組みが全部観察可能なので、「見て確かめる」を繰り返した人から順に強くなる世界なんです。
怪現象は、仕様の顔をして現れます
今日の8つに共通していたのは、これでした。
Linuxの「変な挙動」は、ほとんどが設計どおりの動きを、モデルを知らずに見ているだけです。名前と実体、親と子、シグナルと状態。
モデルを持っている人には、同じ画面が「謎」ではなく「手掛かり」に見えるんですよね。
みなさんがサーバーで出会った怪現象、よかったら教えてください。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。