Fedora 15に最近アップグレードした後、次のエラーが原因で多くのツールが失敗することがわかりました。
tail: inotify resources exhausted
tail: inotify cannot be used, reverting to polling
これは単にtail
inotify問題を報告する以上のものです。どのプロセスがinotifyリソースを消費しているかを調べるためにカーネルを調べる方法はありますか?現在、Inotify関連のsysctl
設定は次のとおりです。
fs.inotify.max_user_instances = 128
fs.inotify.max_user_watches = 8192
fs.inotify.max_queued_events = 16384
答え1
プロセスがinotify_init()を介してinotifyインスタンスを作成すると、/ procファイルシステムのファイル記述子を表す結果ファイルは(存在しない)ファイル「anon_inode:inotify」へのシンボリックリンクであるようです。
$ cd /proc/5317/fd
$ ls -l
total 0
lrwx------ 1 puzel users 64 Jun 24 10:36 0 -> /dev/pts/25
lrwx------ 1 puzel users 64 Jun 24 10:36 1 -> /dev/pts/25
lrwx------ 1 puzel users 64 Jun 24 10:36 2 -> /dev/pts/25
lr-x------ 1 puzel users 64 Jun 24 10:36 3 -> anon_inode:inotify
lr-x------ 1 puzel users 64 Jun 24 10:36 4 -> anon_inode:inotify
概念を誤解しない限り、次のコマンドは、使用するinotifyインスタンスの数に基づいてソートされたプロセスのリスト(/ procに表示されている)を表示する必要があります。
$ for foo in /proc/*/fd/*; do readlink -f $foo; done | grep inotify | sort | uniq -c | sort -nr
犯人を探す
これは@markkcowanが以下のコメントで言及したものです。
$ find /proc/*/fd/* -type l -lname 'anon_inode:inotify' -exec sh -c 'cat $(dirname {})/../cmdline; echo ""' \; 2>/dev/null
答え2
2022年10月31日に更新 以下でMichael Sartainの答えをサポートしてください。。彼は実装したネイティブ実行可能ファイルこれははるかに高速で、私のスクリプト(下)にはない追加機能があります。コンパイルに数秒かかる場合は、試してみる価値があります!
スクリプトを含む元の答え
@Jonathan Kamensが言ったように、時計が使い果たされた可能性があります。私事前作成されたスクリプト、、、inotify-consumers
最悪の犯罪者を一覧表示します。
INOTIFY INSTANCES
WATCHES PER
COUNT PROCESS PID USER COMMAND
------------------------------------------------------------
21270 1 11076 my-user /snap/intellij-idea-ultimate/357/bin/fsnotifier
201 6 1 root /sbin/init splash
115 5 1510 my-user /lib/systemd/systemd --user
85 1 3600 my-user /usr/libexec/xdg-desktop-portal-gtk
77 1 2580 my-user /usr/libexec/gsd-xsettings
35 1 2475 my-user /usr/libexec/gvfsd-trash --spawner :1.5 /org/gtk/gvfs/exec_spaw/0
32 1 570 root /lib/systemd/systemd-udevd
26 1 2665 my-user /snap/snap-store/558/usr/bin/snap-store --gapplication-service
18 2 1176 root /usr/libexec/polkitd --no-debug
14 1 1858 my-user /usr/bin/gnome-shell
13 1 3641 root /usr/libexec/fwupd/fwupd
...
21983 WATCHES TOTAL COUNT
INotify instances per user (e.g. limits specified by fs.inotify.max_user_instances):
INSTANCES USER
----------- ------------------
41 my-user
23 root
1 whoopsie
1 systemd-ti+
...
ここでは、開発システムで8K Observerの基本的な制限が小さすぎる理由をすばやく理解できます。node_modules
WebStormインスタンスは、数千のフォルダがあるフォルダに会うときにこの制限をすばやく最大化するためです。問題がある場合は、Webパックウォッチャーを追加してください...
もともと作成したときは他の選択肢よりはるかに高速でしたが、Simon Matterはロードが多いBig Iron Linux(数百コア)に対していくつかのスピードアップを追加してスピードを10分(!)から15分に減らし、彼のモンスター装備に数秒。
後で、Brian Dowlingがプロセスあたりのインスタンス数に貢献しました。、比較的長い実行時間を犠牲にします。これは、実行時間が約1秒の通常のマシンではマイナーな作業ですが、ビッグアイロンがある場合は必要です。以前のバージョンこれはシステム時間の約1/10です:)
使い方
inotify-consumers --help
答え3
inotifyが不足する可能性があります。よりインスタンスではなく。誰が時計をたくさん作るのかを知るには:
- 追跡を追加するには、監視を有効にしてください。
$ echo 1 > /sys/kernel/debug/tracing/events/syscalls/sys_exit_inotify_add_watch/enable`
tracing_on
sが1であることを確認してください。
$ cat /sys/kernel/debug/tracing/tracing_on
0
$ echo 1 > /sys/kernel/debug/tracing/tracing_on
- 多数のクロックを生成すると疑われるinotifyインスタンスを使用してプロセスを再起動します(Petr Uzelの回答で説明されているように決定されます)。
- ftrace 設定
$ cat /sys/kernel/debug/tracing/current_tracer
nop
$ cat /sys/kernel/debug/tracing/set_ftrace_filter
#### all functions enabled ####
$ echo function > /sys/kernel/debug/tracing/current_tracer
$ echo SyS_inotify_add_watch > /sys/kernel/debug/tracing/set_ftrace_filter
- ファイルを読んで、
/sys/kernel/debug/tracing/trace
いくつかの時計がどのプロセスによって生成されたかを確認してください。
完了したら、echo 0
アクティベーションファイル(またはアクティベーションが必要な場合はtracing_onファイル)に移動してトレースをオフにしても、トレースを続行してもパフォーマンスが低下しません。
メモ:以前のバージョンのLinuxカーネルでは/sys
エンドポイントと呼ばれていましたが、tracing_enabled
今ではと呼ばれていますtracing_on
。以前のバージョンのカーネルを使用している/sys/kernel/debug/tracing/tracing_on
場合/sys/kernel/debug/tracing/tracing_enabled
。
答え4
私はこの問題に直面しており、これらの答えのどれも「どれくらい多いか」を教えてくれません。より現在、各プロセスで使用されていますか? 「テキストの一行でどれだけの数がわかりますか。はいこれはストーリーの一部に過ぎず、コンテンツトラッキングは新しい時計が開いていることを確認するためにのみ役立ちます。
簡単に言うと:inotify
その後、開いているインスタンスのリストと時計数量これを生成したpidとバイナリとともに、時計の数に基づいて降順にソートされます。
sudo lsof | awk '/anon_inode/ { gsub(/[urw]$/,"",$4); print "/proc/"$2"/fdinfo/"$4; }' | while read fdi; do count=$(sudo grep -c inotify $fdi); exe=$(sudo readlink $(dirname $(dirname $fdi))/exe); echo -e $count"\t"$fdi"\t"$exe; done | sort -nr > watches
それは混乱の大きなボールでした。だからそれが私がそこに到達した方法です。まず、tail
テストファイルに対して実行し、開いているファイル記述子を見てみました。
joel@gladstone:~$ tail -f test > /dev/null &
[3] 22734
joel@opx1:~$ ls -ahltr /proc/22734/fd
total 0
dr-xr-xr-x 9 joel joel 0 Feb 22 22:34 ..
dr-x------ 2 joel joel 0 Feb 22 22:34 .
lr-x------ 1 joel joel 64 Feb 22 22:35 4 -> anon_inode:inotify
lr-x------ 1 joel joel 64 Feb 22 22:35 3 -> /home/joel/test
lrwx------ 1 joel joel 64 Feb 22 22:35 2 -> /dev/pts/2
l-wx------ 1 joel joel 64 Feb 22 22:35 1 -> /dev/null
lrwx------ 1 joel joel 64 Feb 22 22:35 0 -> /dev/pts/2
したがって、4は私たちが調査したいfdです。その中に何があるか見てみましょうfdinfo
:
joel@opx1:~$ cat /proc/22734/fdinfo/4
pos: 0
flags: 00
mnt_id: 11
inotify wd:1 ino:15f51d sdev:ca00003 mask:c06 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:1df51500a75e538c
一番下の時計アイテムと同じです!
もう少し時計を使ってみましょう。今回はinotifywait
ユーティリティを使って内部内容を観察してみましょう/tmp
。
joel@gladstone:~$ inotifywait /tmp/* &
[4] 27862
joel@gladstone:~$ Setting up watches.
Watches established.
joel@gladstone:~$ ls -ahtlr /proc/27862/fd | grep inotify
lr-x------ 1 joel joel 64 Feb 22 22:41 3 -> anon_inode:inotify
joel@gladstone:~$ cat /proc/27862/fdinfo/3
pos: 0
flags: 00
mnt_id: 11
inotify wd:6 ino:7fdc sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:dc7f0000551e9d88
inotify wd:5 ino:7fcb sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:cb7f00005b1f9d88
inotify wd:4 ino:7fcc sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:cc7f00006a1d9d88
inotify wd:3 ino:7fc6 sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:c67f00005d1d9d88
inotify wd:2 ino:7fc7 sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:c77f0000461d9d88
inotify wd:1 ino:7fd7 sdev:ca00003 mask:fff ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:d77f00000053c98b
ああ!もっとアイテム!したがって、私たちは6つのものを持つべきです/tmp
:
joel@opx1:~$ ls /tmp/ | wc -l
6
素晴らしい。私の新しいinotifywait
もの一つリストには6つの項目しかありませんがfd
(ここでは別の行で計算される項目)、fdinfo
ファイルには6つの項目があります。したがって、そのファイルを参照して、特定のプロセスの特定のfdが使用している時計の数を見つけることができますfdinfo
。これを上記の一部と一緒に使用して、通知監視が設定されているプロセスのリストを取得し、それを使用して各プロセスを計算しますfdinfo
。これは上記と似ているので、ここに1行だけ捨てます。
sudo lsof | awk '/anon_inode/ { gsub(/[urw]$/,"",$4); print "/proc/"$2"/fdinfo/"$4; }' | while read fdi; do count=$(sudo grep -c inotify $fdi); echo -e $count"\t"$fdi; done
これにはいくつかの重いものがありますが、基本はawk
出力からパスを構築し、pidとfd番号を取得し、後者からu / r / wフラグを削除するために使用することです。次に、ビルドされたパスごとに行数を数え、数とpidを出力します。fdinfo
lsof
fdinfo
inotify
このpidが表すプロセスを同じ場所に置くことは本当に良いでしょうか?私はそう思った。だから、特に混乱している状況では、 pathdirname
でfdinfo
pack を 2 回呼び出してここに/proc/<pid>
追加し、次のように実行することにしました。/exe
readlink
それプロセスのexe名を取得します。それもそこに入れて、時計の数に合わせてソートし、安全な保存のためにファイルにリダイレクトすると、次のような結果が得られます。
sudo lsof | awk '/anon_inode/ { gsub(/[urw]$/,"",$4); print "/proc/"$2"/fdinfo/"$4; }' | while read fdi; do count=$(sudo grep -c inotify $fdi); exe=$(sudo readlink $(dirname $(dirname $fdi))/exe); echo -e $count"\t"$fdi"\t"$exe; done | sort -n > watches
それを実行するいいえsudoは上記で開始したプロセスを示しており、次のような結果が得られます。
joel@gladstone:~$ cat watches
6 /proc/4906/fdinfo/3 /usr/bin/inotifywait
1 /proc/22734/fdinfo/4 /usr/bin/tail
完璧!プロセス、fds、および数のリストよりそれぞれが使用されており、正確に私に必要なものです。