「Everything is a file」の哲学から、サーバーにおける現実的な問題まで
Linuxユーザーにとって、「Everything is a file(すべてはファイルである)」という言葉はお馴染みでしょう。テキストファイルやディレクトリから、ネットワークカードやソケットに至るまで、すべてはカーネルによってファイルディスクリプタ(FD)を介して管理されています。
しかし、現実はそう甘くありません。サーバーが Too many open files エラーを吐いたり、ファイルを削除したのにディスク容量が減らなかったりといったトラブルに直面することがあります。以前、CentOS 7上のECサイトのシステムを管理していた際、Javaアプリケーションで接続リークが発生したことがありました。デフォルトの1024 FDをわずか15分で使い果たし、システム全体が停止してしまったのです。その時、問題のPIDを特定するための救世主となったのが、この lsof (LiSt Open Files) でした。
lsofと他のシステム調査ツールの比較
キャリアの浅いエンジニアは、ポートを調査する際に netstat や ss だけを使いがちです。しかし、それぞれのツールには独自の強みがあり、それらを明確に区別する必要があります。
lsof vs netstat/ss
- netstat/ss: ネットワーク統計に特化し、どのポートが開いているかを表示します。しかし、付随するプロセス情報(PID)が不十分な場合があります。
- lsof: ソケットをファイルディスクリプタの観点から調査します。ポートを特定するだけでなく、そのプロセスがRAMにロードしている
.soライブラリまでリストアップできます。
lsof vs fuser
- fuser: 特定のファイルにアクセスしているプロセスを素早く「kill」するために使用されます。
- lsof: User、FD、Type、Device Sizeなど、ファイルの属性についてより詳細な情報を提供します。
lsof のメリットは、ユーザー、ポート、マウントポイントによる強力なフィルタリング機能です。デメリットは? カーネルの /proc ディレクトリをスキャンするため、何百万ものファイルが同時に開かれているシステムでは、リソースをかなり消費する点です。
「Too Many Open Files」エラー:デフォルト設定を侮るなかれ
このエラーは、プロセスが許可された制限(limit)を超えてファイルを開こうとしたときに発生します。2種類の制限を区別する必要があります:
- Soft Limit: 警告のしきい値。ユーザーが自身で緩和可能。
- Hard Limit: 実際の限界値。root権限のみが変更可能。
原因は通常、アプリのコードのバグ(DB接続の閉じ忘れ)や、Linuxのデフォルト設定が低すぎることによります。NginxやRedisを動かす現代のWebサーバーにとって、デフォルトの1024という数字はあまりにも少なすぎます。
実戦のトラブルシューティングで役立つlsofの5つのテクニック
以下は、本番環境で私がよく使う「鉄板」のコマンドです。
1. ポートを占有しているプロセスを瞬時に特定
Dockerの起動時に Address already in use エラーが出たら、すぐにこのコンボを使いましょう:
# ポート80を占有しているプロセスを調査
sudo lsof -i :80
# LISTEN状態のTCP接続を検索
sudo lsof -nP -iTCP -sTCP:LISTEN
ここで、-n と -P はドメイン名やポート名の解決をスキップし、コマンドを即座に実行するのに役立ちます。
2. 特定のユーザーが開いているファイルを確認
あるアカウントが密かにスクリプトを実行している疑いがある場合に便利です:
sudo lsof -u dev_user
3. 「幽霊ファイル」の特定 — 削除したのに容量が減らない場合
典型的な状況:rm コマンドで50GBの巨大なログファイルを削除したのに、df -h ではディスク使用率が100%のまま。原因は、プロセスがまだそのファイルを保持しているためです。
# 削除済みだがファイルディスクリプタ(FD)が残っているファイルを検索
sudo lsof +L1
サービスを再起動するか、対象のPIDを終了(kill)すれば、即座にディスク容量が解放されます。
4. 使用中のディレクトリ内のファイルを調査
ディスクを umount しようとして device is busy と表示された場合:
sudo lsof +D /data/storage
5. プロセスごとのFD数をカウント
システムエラーの主犯を特定するために、私はこの複合コマンドを使います:
sudo lsof | awk '{print $1, $2}' | sort | uniq -c | sort -rn | head -n 10
結果には、最も多くのファイルを開いているプロセスのトップ10がリストアップされます。
「Too Many Open Files」エラーを根本的に解決する
原因を突き止めたら、システムの制限を引き上げましょう。注意:ulimit は現在のセッションでのみ有効なため、恒久的な設定が必要です。
ステップ1:現状の確認
# 現在のユーザーの制限を確認
ulimit -n
# 特定のPIDの制限を調査
cat /proc/[PID]/limits | grep "Max open files"
ステップ2:恒久的な設定
/etc/security/limits.conf ファイルを編集し、以下の行を追加します:
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
ステップ3:Systemdに関する注意点
Ubuntu 22.04やAlmaLinuxでは、Systemd経由で実行されるサービスは通常 limits.conf を無視します。サービスファイルを直接編集する必要があります:
[Service]
...
LimitNOFILE=65535
...
その後、変更を反映させるために systemctl daemon-reload を実行してください。
おわりに
システム運用において、エラー自体は怖くありません。怖いのは「エラーの場所がわからないこと」です。lsof は単にファイルを表示するコマンドではなく、カーネルがデータフローをどのように運用しているかを理解するためのツールです。サーバーの最適化過程で私が学んだ教訓は、CPUやRAMと同様に、オープンファイル数も常に監視すべきだということです。顧客から苦情が来てから lsof コマンドを探すような事態は避けましょう。

