ルートが使用している開いているファイル記述子の数がulimit -nを超える(またはその方法)のはなぜですか?


13

私たちのサーバーは最近ファイル記述子を使い果たしました。それに関していくつか質問があります。ulimit -n開いているファイル記述子の最大数を提供することになっています。その数は1024です。実行して開いているファイル記述子の数を確認し、lsof -u root |wc -l2500 fdsを取得しました。これは1024をはるかに超えているので、1024の数値は、ユーザーごとではなく、プロセスごとであることを意味すると思います。さて、私は走っlsof -p$PidOfGlassfish|wc -lて1300を得ました。これは私が得られない部分です。ulimit -nユーザーごとまたはプロセスごとのプロセスの最大数ではない場合、それは何に適していますか?rootユーザーには適用されませんか?もしそうなら、どのようにしてファイル記述子の不足に関するエラーメッセージを取得できますか?

編集:私が理解できる唯一の方法ulimit -nは、ファイルハンドルの数ではなく開いているファイルの数(bashマニュアルに記載されているように)を適用する場合です(異なるプロセスが同じファイルを開くことができます)。この場合、開いているファイルの数を一覧表示するだけで(「/」を削除して、メモリにマップされたファイルを除外する)だけで不十分です。

lsof -u root |grep /|sort  -k9  |wc -l #prints '1738'

実際に開いているファイルの数を確認するには、一意のエントリのみを印刷するために名前列でフィルタリングする必要があります。したがって、おそらく次の方がより正確です。

lsof -u root |grep /|sort  -k9 -u |wc -l #prints '604'

上記のコマンドは、lsofからの次の形式での出力を想定しています。

java      32008 root  mem       REG                8,2 11942368      72721 /usr/lib64/locale/locale-archive
vmtoolsd   4764 root  mem       REG                8,2    18624     106432 /usr/lib64/open-vm-tools/plugins/vmsvc/libguestInfo.so

これにより、少なくとも1024未満の数値(によって報告される数値ulimit -n)が得られるため、これは正しい方向への一歩のように思えます。「残念ながら」ファイル記述子が不足しても問題は発生していないため、これを検証するのに苦労します。


2
lsofは、メモリマッピングと開いているファイルを報告するため、「wc」パイプラインは、そのプロセスで使用されるファイル記述子の数の過大評価を生成します。
リチャードケトルウェル

ああ!今では良い情報です。しかし、理解できるかどうかはよくわかりません。「メモリマッピング」とは、メモリマッピングファイルですか?それには私の理解のためにファイルハンドルが必要でしょうか、それともOSがファイルを更新する方法は他にありますか?
オリゴフレン

次の2つ:開いているすべてのファイルハンドルを見つける良い方法は何でしょうか。実際には、「ulimit -n」によって課せられた制限の影響を受けます。
オリゴフレン

1
メモリマッピングには、開いているファイルは必要ありません。開いているファイルのみを一覧表示する場合は、おそらくlsofの出力をフィルタリングするのが最も簡単な方法です。
リチャードケトルウェル

ありがとう、私の答えを編集しました。「lsof -u root | grep / | sort -k9 -u」を使用すると、妥当な答えが得られるようです。これは、少なくともulimit -nより小さい数値です。
オリゴフレン

回答:


9

これをLinuxバージョン2.6.18-164.el5-Red Hat 4.1.2-46でテストしました。プロセスごとにulimitが適用されていることがわかりました。

パラメーターはユーザーレベルで設定されますが、各プロセスに適用されます。

例:1024が制限でした。複数のプロセスが開始され、各プロセスによって開かれたファイルは、

ls -l /proc/--$pid--/fd/ | wc -l

複数のプロセスによって開かれたファイルの合計が1024を超えてもエラーはありませんでした。また、異なるプロセスの結果を組み合わせて一意のファイル数を確認し、一意のファイル数を確認しました。各プロセスのカウントが1024を超えた場合にのみエラーが表示され始めました(java.net.SocketException:Too many open files in process logs)


これをテストしていただきありがとうございます。なぜlsof -p$PidOfGlassfish|wc -l私に1300をくれたのかご存知ですか?カウントの2つのアプローチは何らかの形で異なると思います。そうでない場合、制限はrootユーザーに適用されない可能性がありますか?
オリゴフレン

好奇心が強い、なぜls -l代わりに使用するのlsですか?total 55つのファイルがある場合、後者には余分な行(例:)があります。そのような場合ls -l 、上記の例で使用すると、5ではなく6が報告されますls /proc/<pid>/fd | wc -l。私はを使用します。
スターフライ

@starfryそれは私の側でのずさんなだけです。私は通常、これを段階的に行いls -l、1行につき1つのエントリを提供し、それを別のエントリにパイプします。もちろん、これは通常のパイピングでも発生しますls(そうでない場合)。
オリゴフレン

3

ulimitはファイルハンドル用です。ファイル、ディレクトリ、ソケット、パイプepoll、eventfds、timerfdsなどに適用されます。

プロセスの起動中の任意の時点で、制限が変更された可能性があります。にアクセス/proc/<pid>/limitsして、値が変更されているかどうかを確認します。


3

しゅう

また、どのように実施されたかを判断する"ulimits -Sn"ため"open files"にいくつかのテストを実施しました。

  • linkで言及されているポスターChosenのように、ulimit はプロセスごとに実際に適用されます。プロセスの現在の制限を確認するには:"open files"

    cat /proc/__process_id__/limits

  • プロセスが開いているファイルの数を確認するには、次のコマンドを使用する必要があります。

    lsof -P -M -l -n -d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt' -p __process_id__ -a | awk '{if (NR>1) print}' | wc -l

上記の説明と私の試験方法/結果

"-P -M -l -n"引数のlsofは作るために、単純にあるlsofのは、可能な限り高速で動作します。それらを取り出してください。

-P - inhibits the conversion of port numbers to port names for network files
-M - disable reporting of portmapper registrations for local TCP, UDP and UDPLITE ports
-l - inhibits the conversion of user ID numbers to login names
-n - inhibits the conversion of network numbers to host names for network files

"-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"引数が指示しlsofたタイプのファイル記述子を除外するために:CWD / ERR / LTX / MEM / mmapの/ PD / RTD / TXT。

lsof manページから:

   FD         is the File Descriptor number of the file or:

                   cwd  current working directory;
                   Lnn  library references (AIX);
                   err  FD information error (see NAME column);
                   jld  jail directory (FreeBSD);
                   ltx  shared library text (code and data);
                   Mxx  hex memory-mapped type number xx.
                   m86  DOS Merge mapped file;
                   mem  memory-mapped file;
                   mmap memory-mapped device;
                   pd   parent directory;
                   rtd  root directory;
                   tr   kernel trace file (OpenBSD);
                   txt  program text (code and data);
                   v86  VP/ix mapped file;

"Lnn,jld,m86,tr,v86"Linuxには該当しないと判断したため、除外リストに追加することはありませんでした。わからない"Mxx"

アプリケーションがメモリマップドファイル/デバイスを使用している場合、除外リストから削除"^mem"したい場合があります"^mmap"

編集---切り取り開始---

編集:私はそれを示す次のリンクを見つけました:

メモリマッピングされた.soファイルは、技術的には、アプリケーションが制御するファイルハンドルとは異なります。/ proc // fdは、開いているファイル記述子の測定ポイントです

そのため、プロセスでメモリマップファイルを使用する場合は、*。soファイルを除外する必要があります。

また、SunのJVMはjarファイルメモリマップします

メモリマップされたJARファイル、この場合は「JDKクラス」を保持するファイル。JARをメモリマップすると、JAR内のファイルに非常に効率的にアクセスできます(毎回最初から読み込むのとは対照的です)。Sun JVMは、クラスパス上のすべてのJARをメモリマップします。アプリケーションコードがJARにアクセスする必要がある場合は、メモリマップすることもできます。

そのため、tomcat / glassfishのようなものもメモリマップされたjarファイルを表示します。これらが制限にカウントされるかどうかはテストしいません"ulimit -Sn"

編集---切り取りの終了---

経験的に、プロセスごとのファイル制限(ulimit -Sn)に関してはカウントさないこと"cwd,rtd,txt"がわかりました。

"err,ltx,pd"これらの記述子タイプのファイルハンドルを作成する方法がわからないため、ファイル制限にカウントされるかどうかはわかりません。

"-p __process_id__"引数制限しlsofだけのための情報を返すように__process_id__指定しました。すべてのプロセスのカウントを取得する場合は、これを削除します。

"-a"引数はに使用されている、選択(すなわち「-p」と「-d」引数)。

この"awk '{if (NR>1) print}'"ステートメントはlsof、出力に出力されるヘッダーをスキップするために使用されます。

次のperlスクリプトを使用してテストしました。

File: test.pl
---snip---
#!/usr/bin/perl -w
foreach $i (1..1100) {
  $FH="FH${i}";
  open ($FH,'>',"/tmp/Test${i}.log") || die "$!";
  print $FH "$i\n";
}
---snip---

スクリプトが終了せず、ファイル記述子を解放しないように、perlデバッガーでスクリプトを実行する必要がありました。

実行するには: perl -d test.pl

perlのデバッガーでは、cEnter キーを押してプログラムを実行できます。ulimit -Sn値が1024の場合、Test1017.logファイルを作成した後にプログラムが停止することがわかります/tmp

ここでperlプロセスのpidを識別し、上記のlsofコマンドを使用すると、1024も出力されることがわかります。

を削除し、"wc -l"a "less"に置き換えて、1024個の制限にカウントされたファイルのリストを表示します。"-d ^....."引数も削除して、cwd,txtおよびrtd記述子制限にカウントされなかったことを確認します。

を実行"ls -l /proc/__process_id__/fd/ | wc -l"すると、値1025が返されます。これは、カウントされた出力にヘッダーがls追加されたため"total 0"です。

注意:

OSでファイル記述子が不足しているかどうかを確認するには、次の値を比較することをお勧めします。

cat /proc/sys/fs/file-nr | awk '{print $1}'

cat /proc/sys/fs/file-max

https://www.kernel.org/doc/Documentation/sysctl/fs.txtにはfile-nrそのfile-max意味と意味が記載されています。


0

あなたの推論は、「貴重な記述子を使い果たさないように、この制限を下げる必要があります」のようなもののようです。真実はまったく逆です。サーバーでファイル記述子が足りなくなった場合は、その制限を1,024からそれより大きな値に上げる必要があります。現実的なglassfish実装では、32,768が妥当です。

個人的には、私は常にシステム全体で約8,192に制限を引き上げています-1,024はばかげています。しかし、あなたはもっとglassfish高くしたいと思うでしょう。確認してください/etc/security/limits.conf。ユーザーglassfishとして実行するための特別なエントリを追加できます。


どういう意味で解釈できるのかわかりません:-)私が疑問に思ったのは、なぜそれが当てはまらないのかということです。高く設定しますが、どのように機能するかを理解したいと思います。制限が1024の場合、Glassfishは1300のハンドルをどのように持つことができますか?
オリゴフレン

'lsof -u root | grep / | sort -k9 -u'は、一意のファイル記述子エントリを出力します。これからの行数は、ulimit -nが適用される実際の数だと思います。
オリゴフレン

0

/ proc / sys / fs / file-maxに設定されているシステム全体の制限を確認して、(次の再起動まで)調整するか、sysctl.confにfs.file-maxを設定して永続的にします。これは役に立つかもしれません-http ://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html


1
bashについてのそのコメントは正確ではありません。ulimitは、シェルを介して開始されるプロセスに対して、ユーザーIDごとに制限を課します。これは、オペレーティングシステムのようなUnixでプロセスツリーが生成される方法のおかげで、実質的にすべてです。それはbashではありません。
EightBitTony

申し訳ありません-編集しますが、システム全体の制限に関するコメントはまだ有効です。
rnxrx

彼がシステム全体の制限に達している可能性はほとんどありません。可能ですが、可能性は非常に低いです。
デビッドシュワルツ

EightBitTony:ulimitは、ユーザーIDの制限セットごとにulimitを設定しません。pam_limitsが適用されるときのプロセスごと。「ユーザーごと」であるulimitは、「ulimit -u」「単一ユーザーが使用できるプロセスの最大数」
ユーザー名なし

0

生のlsof呼び出しの結果を想定される制限と比較する一般的な間違い。

グローバル制限(/ proc / sys / fs / file-max)については、/ proc / sys / fs / file-nrを確認する必要があります->最初の値は使用されるものを示し、最後の値は制限です

OpenFileの制限はプロセスごとにありますが、ユーザーに対して定義できます。ユーザーの制限については「ulimit -Hn」コマンドを、定義については/etc/security/limits.confを参照してください。通常、「アプリユーザー」に適用されます。例:「tomcat」:実行するJavaプロセスに適用されるユーザーtomcatに制限を65000に設定します。

プロセスに適用される制限を確認する場合は、そのPIDを取得してから:cat / proc / $ {PID} / limitsプロセスによって開かれているファイルの数を確認する場合は、そのPIDを取得してからls -1 / proc / {PID} / fd | wc -l(lsの場合は「マイナス1」であり、「マイナスel」と混同しないでください)

lsofで詳細を知りたいが、制限の対象となるファイルハンドラーについてのみ知りたい場合は、それらを試してみてください:lsof -p $ {PID} | grep -P "^(\ w + \ s +){3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd、^ err、^ ltx、^ mem、^ mmap、^ pd、^ rtd、 ^ txt '-a

備考:「ファイル」は、ファイル/パイプ/ TCP接続/などです。

rootになるか、sudoを使用してコマンドの正しい結果を取得する必要がある場合があります。権限がなくても、エラーがなく、結果が少ない場合があります。

最後に、プロセスがファイルシステム上のどの「ファイル」にアクセスしているかを知りたい場合は、lsof -p {PID} | grep / | awk '{print $ 9}' | 並べ替え| ユニック

楽しんで !

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.