web-dev-qa-db-ja.com

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

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

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

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によって報告された数)を与えるので、これは正しい方向へのステップのように見えます。 「残念ながら」ファイル記述子が不足する問題は発生していないため、これを検証するのに苦労します。

13
oligofren

これを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:プロセスログ内の開いているファイルが多すぎます)

9
Chosen

@oligofren

また、_"ulimits -Sn"_に対して_"open files"_がどのように適用されているかを確認するために、いくつかのテストを実施しました。

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

    _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

上記の説明と私のテスト方法/結果

lsofへの_"-P -M -l -n"_引数は、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'"_引数は、cwd/err/ltx/mem/mmap/pd/rtd/txtのタイプのファイル記述子を除外するようにlsofに指示します。

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"_を削除することができます。

EDIT ---切り取りの開始---

編集:次の link が見つかりました:

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

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

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

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

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

EDIT --- end snip ---

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

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

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

_"-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のデバッガーでは、cと入力してEnterキーを押すことにより、プログラムを実行できます。_ulimit -Sn_の値が1024、_Test1017.log_に_/tmp_ファイルを作成するとプログラムが停止することがわかります。

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

_"wc -l"_を削除し、_"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_の意味を説明します。

3
Jinesh Choksi

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

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

3
Matthew Ife

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

0
rnxrx

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

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

0
David Schwartz

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

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

OpenFileの制限はプロセスごとにありますが、ユーザーで定義できます。ユーザーの制限についてはコマンド「ulimit -Hn」を、定義については/etc/security/limits.confを参照してください。通常、「app user」で適用されます。例:「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

備考:「ファイル」は、files/pipe/tcp connections /などです。

コマンドの正しい結果を取得するには、おそらくrootになる必要があるか、Sudoを使用する必要がある場合があることに注意してください。権限がない場合は、エラーが発生せず、結果が少なくなります。

最後に、ファイルシステム上の「ファイル」がプロセスによってアクセスされることを知りたい場合は、以下を参照してください。lsof -p {PID} | grep/| awk '{print $ 9}' |並べ替え| uniq

楽しんで !

0
Ronan Kerdudou