症状

nginxのエラーログに too many open files が記録され、接続エラーやレスポンス遅延が発生する。

結論:まずこれを確認

  1. cat /proc/$(cat /var/run/nginx.pid)/limits | grep "Max open files" でnginxプロセスの上限を確認
  2. 上限が低い場合(1024など)は worker_rlimit_nofile と OS の設定を引き上げる
  3. 設定変更後は 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_nofileworker_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_nofileworker_connections × 2 以上を目安にする。ログファイルや設定ファイル用にも余裕を持たせる。

Q2: 設定変更後も反映されない場合は?

A: systemd 環境では LimitNOFILE の設定も必要。systemctl edit nginx で override ファイルを作成し、systemctl daemon-reload 後に systemctl restart nginx を実行する。

Q3: 適切な上限値の目安は?

A: 想定同時接続数 × 2 + 余裕(ログファイル等)で算出する。一般的なWebサーバーでは 65535 が多く使われる。大規模環境では 100000 以上に設定する場合もある。

関連するエラー・症状

  • (関連記事準備中)
  • (関連記事準備中)
  • (関連記事準備中)

解決しない場合