Linuxで「開いているファイルが多すぎます」エラーを解決する方法
公開: 2022-06-29Linuxコンピューターでは、システムリソースはユーザー間で共有されます。 公平なシェアを超えて使用するようにしてください。上限に達します。 また、他のユーザーやプロセスをボトルネックにする可能性があります。
共有システムリソース
Linuxコンピュータのカーネルは、他の膨大な数のジョブの中でも、RAMやCPUサイクルなどの有限のシステムリソースを誰が使用しているかを常に監視しています。 マルチユーザーシステムでは、ユーザーとプロセスが特定のシステムリソースを適切な量よりも多く使用していないことを確認するために、常に注意を払う必要があります。
たとえば、誰かがCPU時間を大量に消費して、他のすべての人にとってコンピュータが遅いと感じることは公平ではありません。 Linuxコンピュータを使用しているのがあなただけであっても、プロセスが使用できるリソースには制限があります。 結局のところ、あなたはまだ別のユーザーです。
RAM、CPUサイクル、ハードドライブ容量など、一部のシステムリソースはよく知られており、明白です。 ただし、監視対象のリソースは非常に多く、各ユーザー(またはユーザーが所有する各プロセス)には上限が設定されています。 これらの1つは、プロセスが一度に開くことができるファイルの数です。
ターミナルウィンドウに「開いているファイルが多すぎます」というエラーメッセージが表示されたり、システムログに表示されたりした場合は、上限に達しており、プロセスがこれ以上ファイルを開くことが許可されていないことを意味します。
開いたファイルだけではありません
Linuxが処理できるオープンファイルの数にはシステム全体の制限があります。 これから説明するように、これは非常に大きな数ですが、まだ制限があります。 各ユーザープロセスには、使用できる割り当てがあります。 それらはそれぞれ、割り当てられたシステム合計のわずかなシェアを取得します。
実際に割り当てられるのは、いくつかのファイルハンドルです。 開かれる各ファイルにはハンドルが必要です。 かなり寛大な割り当てがあっても、システム全体で、ファイルハンドルは最初に想像するよりも早く使い果たされる可能性があります。
Linuxはほとんどすべてを抽象化して、ファイルのように見せます。 時には、それらは単なる古いファイルになります。 ただし、ディレクトリを開くなどの他のアクションでもファイルハンドルが使用されます。 Linuxは、ハードウェアデバイスの一種のドライバーとしてブロック特殊ファイルを使用します。 文字特殊ファイルは非常に似ていますが、パイプやシリアルポートなど、スループットの概念を持つデバイスでよく使用されます。
ブロック特殊ファイルは一度にデータのブロックを処理し、文字特殊ファイルは各文字を個別に処理します。 これらの特別なファイルは両方とも、ファイルハンドルを使用してのみアクセスできます。 プログラムが使用するライブラリはファイルハンドルを使用し、ストリームはファイルハンドルを使用し、ネットワーク接続はファイルハンドルを使用します。
これらのさまざまな要件をすべて抽象化してファイルとして表示することで、それらとのインターフェースが簡素化され、パイプやストリームなどが機能できるようになります。
Linuxが舞台裏でファイルを開き、ファイルハンドルを使用して自分自身を実行していることがわかります。ユーザープロセスを気にする必要はありません。 開いているファイルの数は、開いたファイルの数だけではありません。 オペレーティングシステムのほとんどすべてがファイルハンドルを使用しています。
ファイルハンドルの制限
このコマンドを使用すると、システム全体のファイルハンドルの最大数を確認できます。
cat / proc / sys / fs / file-max
これは、途方もなく大きな数の9.2兆を返します。 これが理論上のシステムの最大値です。 これは、64ビットの符号付き整数で保持できる最大の値です。 貧弱なコンピュータが、一度に開いている多くのファイルに実際に対処できるかどうかは、まったく別の問題です。
ユーザーレベルでは、開いているファイルの最大数に明示的な値はありません。 しかし、大まかに解決することはできます。 プロセスの1つが開くことができるファイルの最大数を見つけるために、 -n
(ファイルを開く)オプションを指定してulimit
コマンドを使用できます。
ulimit -n
また、ユーザーが持つことができるプロセスの最大数を見つけるために、 -u
(ユーザープロセス)オプションを指定してulimit
を使用します。
ulimit -u
1024と7640を掛けると、7,823,360になります。 もちろん、これらのプロセスの多くは、デスクトップ環境やその他のバックグラウンドプロセスですでに使用されています。 つまり、これはもう1つの理論上の最大値であり、現実的には達成できないものです。
重要な数値は、プロセスが開くことができるファイルの数です。 デフォルトでは、これは1024です。同じファイルを1024回同時に開くことは、1024個の異なるファイルを同時に開くことと同じであることに注意してください。 すべてのファイルハンドルを使い切ったら、完了です。
プロセスが開くことができるファイルの数を調整することが可能です。 この数値を調整するときは、実際には2つの値を考慮する必要があります。 1つは、現在設定されている値、または設定しようとしている値です。 これはソフトリミットと呼ばれます。 ハード制限もあり、これはソフト制限を上げることができる最高値です。
これについて考える方法は、ソフト制限は実際には「現在の値」であり、上限は現在の値が到達できる最大値です。 通常のroot以外のユーザーは、ソフト制限をハード制限までの任意の値に上げることができます。 rootユーザーは、ハード制限を増やすことができます。
現在のソフト制限とハード制限を確認するには、 ulimit
を-S
(ソフト)および-H
(ハード)オプション、および-n
(ファイルを開く)オプションとともに使用します。
ulimit -Sn
ulimit -Hn
ソフト制限が適用されていることを確認できる状況を作成するために、失敗するまでファイルを繰り返し開くプログラムを作成しました。 次に、キーストロークを待ってから、使用していたすべてのファイルハンドルを放棄します。 このプログラムはopen-files
と呼ばれます。
./open-ファイル
1021ファイルを開き、ファイル1022を開こうとすると失敗します。
1024から1021を引いたものは3です。他の3つのファイルハンドルはどうなりましたか? これらは、 STDIN
、 STDOUT
、およびSTDERR
ストリームに使用されました。 プロセスごとに自動的に作成されます。 これらのファイル記述子の値は常に0、1、および2です。
関連: Linuxlsofコマンドの使用方法
これらは、 -p
(プロセス)オプションを指定したlsof
コマンドと、 open-files
プログラムのプロセスIDを使用して確認できます。 便利なことに、プロセスIDをターミナルウィンドウに出力します。
lsof -p 11038
もちろん、実際の状況では、どのプロセスがすべてのファイルハンドルを飲み込んだのかわからない場合があります。 調査を開始するには、この一連のパイプコマンドを使用できます。 それはあなたにあなたのコンピュータのファイルハンドルの15人の最も多作なユーザーを教えてくれます。
lsof | awk'{print $ 1 "" $ 2; }'| 並べ替え-rn| uniq -c | 並べ替え-rn| 頭-15
より多くのまたはより少ないエントリを表示するには、 -15
パラメータをhead
コマンドに調整します。 プロセスを特定したら、プロセスが不正になり、制御不能なために開いているファイルが多すぎるのか、それとも本当にそれらのファイルが必要なのかを把握する必要があります。 それらが必要な場合は、ファイルハンドルの制限を増やす必要があります。
ソフト制限を増やす
ソフト制限を増やしてプログラムを再度実行すると、さらに多くのファイルが開かれるはずです。 ulimit
コマンドと-n
(ファイルを開く)オプションを数値2048で使用します。これが新しいソフト制限になります。
ulimit -n 2048
今回は2045ファイルを正常に開きました。 予想どおり、 STDIN
、 STDOUT
、およびSTDERR
に使用されるファイルハンドルのため、これは2048より3つ少なくなります。
恒久的な変更を行う
ソフト制限を増やすと、現在のシェルにのみ影響します。 新しいターミナルウィンドウを開き、ソフト制限を確認します。 古いデフォルト値であることがわかります。 ただし、プロセスが保持できるオープンファイルの最大数に新しいデフォルト値をグローバルに設定する方法があります。これは永続的であり、再起動後も存続します。
古いアドバイスでは、「/ etc/sysctl.conf」や「/etc/security/limits.conf」などのファイルを編集することを推奨することがよくあります。 ただし、systemdベースのディストリビューションでは、特にグラフィカルログインセッションの場合、これらの編集は一貫して機能しません。
ここに示す手法は、systemdベースのディストリビューションでこれを行う方法です。 処理する必要のあるファイルは2つあります。 1つ目は「/etc/systemd/system.conf」ファイルです。 sudo
を使用する必要があります。
sudo gedit /etc/systemd/system.conf
文字列「DefaultLimitNOFILE」を含む行を検索します。 行の先頭からハッシュ「#」を削除し、最初の数字を、プロセスの新しいソフト制限にしたいものに編集します。 4096を選択しました。その行の2番目の数字はハードリミットです。 これは調整しませんでした。
ファイルを保存して、エディターを閉じます。
「/etc/systemd/user.conf」ファイルでその操作を繰り返す必要があります。
sudo gedit /etc/systemd/user.conf
文字列「DefaultLimitNOFILE」を含む行にも同じ調整を行います。
ファイルを保存して、エディターを閉じます。 コンピューターを再起動するか、 daemon-reexec
オプションを指定してsystemctl
コマンドを使用して、 systemd
が再実行され、新しい設定が取り込まれるようにする必要があります。
sudosystemctlデーモン-reexec
ターミナルウィンドウを開いて新しい制限を確認すると、設定した新しい値が表示されます。 私たちの場合、それは4096でした。
ulimit -n
file-greedyプログラムを再実行することで、これが実際の運用上の価値であることをテストできます。
./open-ファイル
プログラムはファイル番号4094を開くことができません。これは、4093が開かれたファイルであることを意味します。 これが期待値であり、3は4096未満です。
すべてがファイルです
Linuxがファイルハンドルに大きく依存しているのはそのためです。 今、あなたがそれらを使い果たし始めたら、あなたはあなたの割り当てを増やす方法を知っています。
関連: Linuxのstdin、stdout、およびstderrとは何ですか?