症状
nginxのエラーログに too many open files が記録され、接続エラーやレスポンス遅延が発生する。
結論:まずこれを確認
cat /proc/$(cat /var/run/nginx.pid)/limits | grep "Max open files"でnginxプロセスの上限を確認- 上限が低い場合(1024など)は
worker_rlimit_nofileと OS の設定を引き上げる - 設定変更後は
systemctl restart nginxで反映
トラブルシューティングフロー
flowchart TD
A[too many open files 発生] --> B{エラーログを確認}
B --> C[nginx プロセスの上限を確認]
C --> D{上限が低い?}
D -->|Yes| E[nginx.conf を確認]
D -->|No| F[接続数が異常に多い可能性]
E --> G{worker_rlimit_nofile 設定あり?}
G -->|No| H[worker_rlimit_nofile を追加]
G -->|Yes| I[OS の ulimit を確認]
I --> J{OS 上限が低い?}
J -->|Yes| K[/etc/security/limits.conf を編集]
J -->|No| L[systemd の LimitNOFILE を確認]
F --> M[アクセスログ・接続元を調査]
H --> N[nginx を再起動]
K --> N
L --> N
よくある原因
- nginx.conf に worker_rlimit_nofile が未設定 - デフォルトでは OS の soft limit を継承する
- OS の ulimit が低い - 多くのディストリビューションでデフォルト 1024
- systemd の LimitNOFILE が制限 - systemd 経由で起動すると別の上限が適用される
- worker_connections が高すぎる - 接続数 × 2(クライアント+upstream)のファイルディスクリプタが必要
- keepalive_timeout が長すぎる - 接続が長時間保持されファイルディスクリプタを消費
- DDoS やクローラーによる大量接続 - 想定外のアクセス集中
- upstream への接続が滞留 - バックエンドの応答遅延で接続が解放されない
確認手順
ステップ1: エラーログを確認する
tail -100 /var/log/nginx/error.log | grep "open files"
🔍 チェックポイント: [alert] ... open() ... failed (24: Too many open files) のようなメッセージが出力される
ステップ2: nginx プロセスの現在の上限を確認する
# nginx の PID を取得
cat /var/run/nginx.pid
# または
pgrep -o nginx
# プロセスの limits を確認(PID を指定)
cat /proc/$(cat /var/run/nginx.pid)/limits | grep "Max open files"
🔍 チェックポイント: Soft Limit と Hard Limit の値を確認。1024 以下の場合は引き上げが必要
ステップ3: 現在のファイルディスクリプタ使用数を確認する
# nginx worker プロセスの fd 数を確認
for pid in $(pgrep nginx); do
echo "PID $pid: $(ls /proc/$pid/fd 2>/dev/null | wc -l)"
done
🔍 チェックポイント: 使用数が上限に近い場合、上限引き上げが必要
ステップ4: nginx.conf の設定を確認する
grep -E "worker_rlimit_nofile|worker_connections" /etc/nginx/nginx.conf
🔍 チェックポイント: worker_rlimit_nofile が設定されているか確認。未設定の場合は追加する
ステップ5: nginx.conf に worker_rlimit_nofile を設定する
# nginx.conf の先頭(events ブロックの外)に追加
# worker_rlimit_nofile 65535;
設定例(nginx.conf):
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
}
🔍 チェックポイント: worker_rlimit_nofile は worker_connections × 2 以上を目安に設定
ステップ6: OS の上限を確認・変更する
# 現在のユーザーの上限を確認
ulimit -n
# システム全体の上限を確認
cat /proc/sys/fs/file-max
/etc/security/limits.conf に追加:
# nginx ユーザーの上限を引き上げ
nginx soft nofile 65535
nginx hard nofile 65535
# または全ユーザー
* soft nofile 65535
* hard nofile 65535
🔍 チェックポイント: 変更後は再ログインまたはシステム再起動で反映
ステップ7: systemd の設定を確認する(systemd 環境の場合)
# nginx の systemd unit ファイルを確認
systemctl cat nginx | grep LimitNOFILE
設定がない場合、override ファイルを作成:
sudo systemctl edit nginx
以下を追加:
[Service]
LimitNOFILE=65535
🔍 チェックポイント: systemctl daemon-reload && systemctl restart nginx で反映
ステップ8: 設定を反映して確認する
# 設定ファイルの構文チェック
nginx -t
# nginx を再起動
systemctl restart nginx
# 上限が反映されたか確認
cat /proc/$(cat /var/run/nginx.pid)/limits | grep "Max open files"
🔍 チェックポイント: Soft Limit が設定した値になっていれば成功
NG行動(やってはいけないこと)
- nginx -s reload だけで済ませる - worker_rlimit_nofile の変更は reload では反映されない
- 上限を無制限(unlimited)に設定する - システムリソースを枯渇させるリスクがある
- worker_connections だけを増やす - ファイルディスクリプタ上限も合わせて増やす必要がある
- 本番環境で検証なしに設定変更する - nginx -t で構文チェックしてから反映する
- OS の file-max より大きい値を設定する - システム全体の上限を超えることはできない
よくある質問(FAQ)
Q1: worker_rlimit_nofile と worker_connections の関係は?
A: 1つの接続でクライアント側とupstream側の2つのファイルディスクリプタを使用する。worker_rlimit_nofile は worker_connections × 2 以上を目安にする。ログファイルや設定ファイル用にも余裕を持たせる。
Q2: 設定変更後も反映されない場合は?
A: systemd 環境では LimitNOFILE の設定も必要。systemctl edit nginx で override ファイルを作成し、systemctl daemon-reload 後に systemctl restart nginx を実行する。
Q3: 適切な上限値の目安は?
A: 想定同時接続数 × 2 + 余裕(ログファイル等)で算出する。一般的なWebサーバーでは 65535 が多く使われる。大規模環境では 100000 以上に設定する場合もある。
関連するエラー・症状
- (関連記事準備中)
- (関連記事準備中)
- (関連記事準備中)
解決しない場合
- nginx 公式ドキュメント - Controlling nginx
- nginx 公式ドキュメント - Core functionality
- 確認すべきログ:
/var/log/nginx/error.log,/var/log/syslog - 次に調べるキーワード:
nginx connection limit,linux file descriptor tuning,sysctl fs.file-max