プロセスがinotifyで監視しているオブジェクトの数を取得する
inotifyを使っていると、プロセスが監視しているファイルの数がfs.inotify.max_user_watches
の値を上回ってno space left on device
のエラーとなる…ということはよくあるのだけど、じゃあ今いくつ監視しているのか?を知りたくなるので調べた。結論としては、プロセスがオープンしいるinotifyインスタンスに監視中のオブジェクト一覧が保存されており、数えると知ることができる。
まずは調査用のプロセスが欲しいので、無限にファイルを作りそれを監視するプログラムを用意する。
package main
import (
"fmt"
"github.com/fsnotify/fsnotify"
"log"
"os"
"time"
)
func NewWatcher() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
log.Println("event:", event)
if event.Op&fsnotify.Write == fsnotify.Write {
log.Println("modified file:", event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("error:", err)
}
}
}()
i := 1
for {
path := fmt.Sprintf("/tmp/foo_%d.txt", i)
_, err := os.Create(path)
if err != nil {
log.Fatal(err)
}
err = watcher.Add(path)
if err != nil {
log.Fatal(err)
}
fmt.Printf("start watching %s\n", path)
i += 1
time.Sleep(1 * time.Second)
}
<-done
}
func main() {
NewWatcher()
}
このプログラムを実行したあと(プロセスIDは4244)、/proc/32531/fd
を見てみる。anon_inode:inotify
へのリンクになっている3
が調査対象となるfd。
ubuntu@alpaca-dev:~$ ls -ahltr /proc/4244/fd
total 0
dr-xr-xr-x 9 ubuntu ubuntu 0 Nov 25 13:28 ..
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 9 -> /tmp/foo_2.txt
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 8 -> 'anon_inode:[eventpoll]'
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 7 -> /tmp/foo_1.txt
l-wx------ 1 ubuntu ubuntu 64 Nov 25 13:28 6 -> 'pipe:[548152]'
lr-x------ 1 ubuntu ubuntu 64 Nov 25 13:28 5 -> 'pipe:[548152]'
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 4 -> 'anon_inode:[eventpoll]'
lr-x------ 1 ubuntu ubuntu 64 Nov 25 13:28 3 -> anon_inode:inotify
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 2 -> /dev/pts/2
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 14 -> /tmp/foo_7.txt
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 13 -> /tmp/foo_6.txt
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 12 -> /tmp/foo_5.txt
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 11 -> /tmp/foo_4.txt
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 10 -> /tmp/foo_3.txt
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 1 -> /dev/pts/2
lrwx------ 1 ubuntu ubuntu 64 Nov 25 13:28 0 -> /dev/pts/2
dr-x------ 2 ubuntu ubuntu 0 Nov 25 13:28 .
次に、/proc/4244/fdinfo/3
の中を見てみると、監視しているディスクリプタ一覧がある。inotify
から始まる行を数えると、そのinotifyインスタンスで監視しているファイル数がわかる。
ubuntu@alpaca-dev:~$ cat /proc/4244/fdinfo/3
pos: 0
flags: 02000000
mnt_id: 13
inotify wd:10 ino:1a9d sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:9d1a00007e8b11e5
inotify wd:f ino:1a9c sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:9c1a0000a2cbafb8
inotify wd:e ino:1a9a sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:9a1a0000d962ed0a
inotify wd:d ino:1a99 sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:991a00005d758c3d
inotify wd:c ino:1a73 sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:731a0000aa47aa90
inotify wd:b ino:1a72 sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:721a0000d00cc24f
inotify wd:a ino:1a6e sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:6e1a0000c3e218c9
inotify wd:9 ino:1a4d sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:4d1a00007a377089
inotify wd:8 ino:1a3e sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:3e1a0000cdc73ba9
inotify wd:7 ino:1a26 sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:261a00008ce7205f
inotify wd:6 ino:1a23 sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:231a0000f8d65bf0
inotify wd:5 ino:1a22 sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:221a00003cc01fa5
inotify wd:4 ino:18f9 sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:f9180000870fe1f0
inotify wd:3 ino:18e5 sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:e5180000d052e2f0
inotify wd:2 ino:9e sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:9e0000002427522c
inotify wd:1 ino:6e sdev:fc00001 mask:fc6 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:6e00000094549bc1
これをメトリクス化すれば、no space left on device
エラーが発生した時に監視対象がmax_user_watchesの値を越えそうになっているのだな、ということが確認できるのではないか?
参考文献