repl.info

プロセスが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の値を越えそうになっているのだな、ということが確認できるのではないか?

参考文献