Linuxで「Too many open files」が出たときの確認方法|原因と解決手順

Linuxサーバーでアプリケーションを動かしていると、突然ログに「Too many open files」と表示されたり、新しい接続を受け付けられなくなったりすることがあります。

このエラーは、プロセスが使用できるファイルディスクリプタの上限に達したときなどに発生します。

ファイルディスクリプタは、ファイルだけでなく、ネットワーク接続やパイプなどを扱う際にも使われます。そのため、Webサーバーやデータベース、常時接続を扱うアプリケーションでも問題になることがあります。

原因を調べるときは、単純に上限を引き上げるのではなく、どのプロセスが、どの程度ファイルディスクリプタを使用しているのかを確認することが重要です。

「Too many open files」とは?

Linuxでは、プロセスがファイルやネットワーク接続などを扱う際に、ファイルディスクリプタ(FD)という番号を使用します。

例えば、次のような処理で使用されます。

  • ファイルの読み書き
  • Webサーバーのネットワーク接続
  • データベースへの接続
  • ログファイルへの出力
  • パイプを使ったプロセス間通信

プロセスが同時に多くの接続やファイルを扱うと、使用するファイルディスクリプタも増えます。

設定された上限に達すると、新しいファイルを開いたり接続を確立したりする処理が失敗し、「Too many open files」というエラーが発生する場合があります。

ただし、エラーが発生したからといって、必ずしもサーバー全体のファイル数が多すぎるわけではありません。特定のプロセスだけが上限に達している可能性もあります。

まずはulimitで上限を確認する

最初に、現在のシェルで設定されているファイルディスクリプタの上限を確認します。

ulimit -n

例えば、次のように表示されたとします。

1024

これは、現在のシェルと、そこから起動するプロセスに適用されるファイルディスクリプタ数の上限を示しています。

ただし、この数値がサーバー上のすべてのプロセスに共通するわけではありません。

systemdから起動したサービスや、別のユーザーで実行されているアプリケーションでは、異なる上限が適用されていることがあります。

そのため、エラーが発生しているサービスについても確認する必要があります。

プロセスが使用しているファイル数を調べる

まず、エラーが発生しているプロセスのPIDを確認します。

例えば、Nginxの場合は次のコマンドを使えます。

pgrep -a nginx

アプリケーション名が分かっている場合は、その名前に置き換えてください。

PIDが分かったら、次のコマンドで開いているファイルディスクリプタを確認します。

ls -l /proc/PID/fd

PIDの部分は実際のプロセスIDに置き換えます。

例えば、PIDが1234なら次のようになります。

ls -l /proc/1234/fd

現在開いているファイルやソケットなどを確認できます。アクセス権限やプロセスの終了状況によっては、情報を取得できないこともあります。

ファイルディスクリプタの数だけを確認したい場合は、次の方法もあります。

find /proc/1234/fd -maxdepth 1 -type l | wc -l

この数値を、プロセスに適用されている上限と比較すると、上限に近づいているかどうかを判断しやすくなります。

lsofで使用状況を詳しく調べる

lsofコマンドを使うと、プロセスが開いているファイルやソケットなどを詳しく確認できます。

インストールされている場合は、次のように実行します。

sudo lsof -p 1234

ここではPIDを1234としています。実際のプロセスIDに置き換えてください。

ファイルディスクリプタの数を概算する場合は、次のような方法もあります。

sudo lsof -nP -p 1234 | wc -l

ただし、ヘッダーなども数えるため、厳密なファイルディスクリプタ数ではありません。正確な数を確認したい場合は、/proc/PID/fdの内容と照らし合わせてください。

確認するときは、次の点に注目します。

  • 同じファイルが大量に開かれていないか
  • ネットワーク接続が増え続けていないか
  • ログファイルが想定どおりに扱われているか
  • 不要になった接続が残っていないか

例えば、アプリケーションが使用済みの接続を適切に閉じていない場合、ファイルディスクリプタが徐々に増加することがあります。

このような場合は、上限を引き上げるだけでは根本的な解決になりません。

systemdで起動したサービスの上限を確認する

Nginxや独自のアプリケーションなどをsystemdで管理している場合、シェルのulimit -nだけではサービスの設定を正しく判断できません。

まず、対象サービスの状態を確認します。

systemctl status nginx

続いて、systemd側で設定されているファイルディスクリプタの上限を確認します。

systemctl show nginx -p LimitNOFILE

出力例:

LimitNOFILE=65535

これは、Nginxサービスに設定されている上限の例です。実際の値は環境によって異なります。

独自のアプリケーションであれば、nginxの部分を該当するサービス名に置き換えます。

例えば、サービス名がmyapp.serviceなら次のようにします。

systemctl show myapp.service -p LimitNOFILE

設定値が十分に大きく見えても、実際に起動しているプロセスの制限や、アプリケーション内部の制約によってエラーが発生する場合があります。

必要に応じて、実際のプロセスの情報も確認してください。

LimitNOFILEを変更する方法

調査の結果、サービスに設定されている上限が処理量に対して不足しており、アプリケーション側にも問題がないと判断できた場合は、systemdの設定変更を検討します。

まず、対象サービスの現在の設定と、アプリケーションが必要とするファイルディスクリプタ数を確認してください。

設定を上書きするには、次のコマンドを使います。

sudo systemctl edit myapp.service

エディターが開いたら、次の設定を記述します。

[Service]
LimitNOFILE=65535

myapp.serviceと65535は例です。実際のサービス名と必要な上限に合わせて変更してください。

保存したら、systemdに設定を再読み込みさせます。

sudo systemctl daemon-reload

続いて、対象サービスを再起動します。

sudo systemctl restart myapp.service

再起動後、設定が反映されているかを確認します。

systemctl show myapp.service -p LimitNOFILE

注意: サービスの再起動によって、接続中の利用者や実行中の処理に影響が出る場合があります。本番環境では、事前に影響範囲を確認し、必要に応じてメンテナンス時間を確保してください。

また、上限を大きくすれば必ず解決するわけではありません。ファイルディスクリプタのリークや、不要な接続が増え続けている問題がある場合は、アプリケーション側の修正も必要です。

Too many open filesが発生する主な原因

原因を調べる際は、次のように分類すると整理しやすくなります。

原因確認するポイント
ファイルディスクリプタの上限不足ulimit -n、LimitNOFILE
ファイルを閉じ忘れている/proc/PID/fd、lsof
接続が増え続けているソケット数、アプリケーションログ
サービス設定が不足しているsystemdの設定、サービスの実行条件
アプリケーションの不具合ログ、使用しているライブラリ、接続管理処理

特に、ファイルディスクリプタの使用数が時間とともに増え続ける場合は注意が必要です。

一時的なアクセス増加なのか、接続が解放されない問題なのかを区別するため、時間を空けて複数回確認すると原因を絞り込みやすくなります。

エラーが出たときの確認手順

実際に問題が発生した場合は、次の順番で確認すると効率的です。

  1. エラーログから対象のサービスと発生時刻を確認する
  2. ulimit -nで現在のシェルの上限を確認する
  3. /proc/PID/fdやlsofで対象プロセスの使用状況を調べる
  4. systemctl show サービス名 -p LimitNOFILEでサービスの設定を確認する
  5. 使用数が増え続けている場合は、接続管理やファイルの閉じ忘れを調べる
  6. 上限不足が確認できた場合に限り、必要な範囲で設定を見直す
  7. 修正後にログと使用状況を再確認する

この手順なら、原因を特定しないまま上限だけを変更するリスクを減らせます。

まとめ

Linuxで「Too many open files」が発生した場合は、まずファイルディスクリプタの使用状況と上限を確認することが重要です。

基本となるコマンドは次の3つです。

ulimit -n
ls -l /proc/PID/fd
systemctl show サービス名 -p LimitNOFILE

必要に応じてlsofも使い、どのプロセスがファイルや接続を多く使用しているのかを調べます。

上限が不足している場合はsystemdのLimitNOFILEなどを見直せますが、ファイルの閉じ忘れや接続管理の問題が原因なら、アプリケーション側の修正も必要です。

エラーを解消するだけでなく、ファイルディスクリプタが増えた原因まで確認することが、再発防止につながります。

Too many open filesはサーバーのメモリ不足が原因ですか?

必ずしもそうではありません。ファイルディスクリプタの上限に達したことが直接の原因である場合があります。メモリ使用量だけで判断せず、プロセスの使用状況と上限を確認してください。

ulimit -nを大きくすれば解決しますか?

上限不足が原因なら改善する可能性があります。ただし、サービスの起動方法によって適用される設定が異なります。また、ファイルや接続を閉じ忘れている場合は、上限を変更しても再発する可能性があります。

systemdのLimitNOFILEはどこで確認できますか?

次のコマンドで確認できます。

systemctl show サービス名 -p LimitNOFILE

サービス名は、実際にエラーが発生しているサービスに置き換えてください。

lsofがインストールされていない場合はどうすればいいですか?

/proc/PID/fdを利用して、プロセスが開いているファイルディスクリプタを確認できます。lsofは詳細な調査に便利ですが、必須ではありません。

上限を変更したらサーバーを再起動する必要がありますか?

通常、systemdのサービス設定を変更した場合は、systemdの再読み込みと対象サービスの再起動が必要です。サーバー全体の再起動が常に必要というわけではありません。

類似投稿