おいしい健康 開発者ブログ

株式会社おいしい健康で働くエンジニア・デザイナーが社内の様子をお伝えします。

Linuxでプロセスごとに開いているファイルディスクリプタの数を調べる

こんにちは 山下(@tomorrowkey) です。

Linuxをセットアップする時にすぐに数を大きくするfile descriptorの数ですが、どのプロセスがどのくらいファイルを開いているか確認する方法を知らなかったので調べました。 早速最終的なコマンドから。例えばunicornが開いているファイルの数を調べるならこんな感じ。

for i in $(ps aux | grep "[u]nicorn" | awk '{print $2}'); do  ls /proc/$i/fd | wc -l; done

開いているファイルディスクリプタ/proc/$PID/fdにあるので、数を数えればOKです。
調べたことなど書きます。

dockerでfile descriptorの数を設定する

検証にはdockerを使います。 起動時に--ulimitというオプションを渡すだけで制限が可能です。 検証用なので極端に小さく設定します。

$ docker run --ulimit="nofile=64" --rm -it ruby:2.4.2-jessie /bin/bash
root@ea6e45c79d10:/# ulimit -n
64

irbを起動しただけのfile descriptorの数を調べる

プロセスIDを調べます。

# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  20244  3208 pts/0    Ss   00:35   0:00 /bin/bash
root         7  0.1  0.1  20244  3196 pts/1    Ss   00:35   0:00 /bin/bash
root        14  1.6  0.4  47672  9632 pts/0    Sl+  00:35   0:00 irb
root        16  0.0  0.1  17500  2072 pts/1    R+   00:35   0:00 ps aux

file descriptorの数を調べます。

# ls /proc/14/fd | wc -l
9

9個でした。

今度はlsofで数を確認します。 rubyのdockerイメージにはlsofがインストールされていないので、インストールします。

# apt-get update && apt-get install -y lsof
# lsof -p 14
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
irb      14 root  cwd    DIR   0,46     4096   52302 /
irb      14 root  rtd    DIR   0,46     4096   52302 /
irb      14 root  txt    REG  254,1   146248 3145942 /usr/local/bin/ruby
irb      14 root  mem    REG  254,1   171800 1444564 /lib/x86_64-linux-gnu/libtinfo.so.5.9
irb      14 root  mem    REG  254,1   151120 1444515 /lib/x86_64-linux-gnu/libncurses.so.5.9
irb      14 root  mem    REG  254,1   297040 1444546 /lib/x86_64-linux-gnu/libreadline.so.6.3
irb      14 root  mem    REG  254,1   260648 3146915 /usr/local/lib/ruby/2.4.0/x86_64-linux/readline.so
irb      14 root  mem    REG  254,1   292976 3146919 /usr/local/lib/ruby/2.4.0/x86_64-linux/stringio.so
irb      14 root  mem    REG  254,1    33400 3146874 /usr/local/lib/ruby/2.4.0/x86_64-linux/enc/trans/transdb.so
irb      14 root  mem    REG  254,1   183168 3146831 /usr/local/lib/ruby/2.4.0/x86_64-linux/enc/encdb.so
irb      14 root  mem    REG  254,1  1738176 1444479 /lib/x86_64-linux-gnu/libc-2.19.so
irb      14 root  mem    REG  254,1  1051056 1444509 /lib/x86_64-linux-gnu/libm-2.19.so
irb      14 root  mem    REG  254,1    35176 1444487 /lib/x86_64-linux-gnu/libcrypt-2.19.so
irb      14 root  mem    REG  254,1    14664 1444492 /lib/x86_64-linux-gnu/libdl-2.19.so
irb      14 root  mem    REG  254,1   137384 1444543 /lib/x86_64-linux-gnu/libpthread-2.19.so
irb      14 root  mem    REG  254,1 15803280 3145980 /usr/local/lib/libruby.so.2.4.2
irb      14 root  mem    REG  254,1   140928 1444461 /lib/x86_64-linux-gnu/ld-2.19.so
irb      14 root    0u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    1u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    2u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    3r  FIFO   0,10      0t0   54293 pipe
irb      14 root    4w  FIFO   0,10      0t0   54293 pipe
irb      14 root    5r  FIFO   0,10      0t0   54294 pipe
irb      14 root    6w  FIFO   0,10      0t0   54294 pipe
irb      14 root    7u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    8u   CHR  136,0      0t0       3 /dev/pts/0

FDカラムに注目すると…

  • cwd -> current working directory
  • rtd -> root directory
  • txt -> program text
  • mem -> memory-mapped device
  • \[0-9]+r\ -> read-onlyで開いているファイル
  • \[0-9]+w\ -> write-onlyで開いているファイル
  • \[0-9]+u\ -> read-writeで開いてるファイル

lsofでfile descriptorの数を調べるにはFDが数字から始まるものを数えるとよさそう。 その他の値についてはこちら https://linux.die.net/man/8/lsof

lsofを使えばどのファイルを開いているかまで分かります。

たくさんのファイルを開いてfile descriporの数を調べる

スクリプトでファイルをたくさん開きます。

files = []
(1..(2 ** 10)).each do |i|
  puts i
  files << File.open("#{i}", "w")
  sleep 0.5
end
1
2
3
# ...
54
55
56
Errno::EMFILE: Too many open files @ rb_sysopen - 56
    from (irb):4:in `initialize'
  from (irb):4:in `open'
  from (irb):4:in `block in irb_binding'
    from (irb):2:in `each'
  from (irb):2
  from /usr/local/bin/irb:11:in `<main>'

無事ファイルの開き過ぎでエラーを吐きました。 irbをそのままに、違うターミナルでfile descriptorの数を調べます。

# for i in $(ps aux | grep "[i]rb" | awk '{print $2}'); do  ls /proc/$i/fd | wc -l; done
64

lsofで確認します。

# lsof -p $(ps aux | grep "[i]rb" | awk '{print $2}' | tr -d " ")
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
irb      14 root  cwd    DIR   0,46     4096   52302 /
irb      14 root  rtd    DIR   0,46     4096   52302 /
irb      14 root  txt    REG  254,1   146248 3145942 /usr/local/bin/ruby
irb      14 root  mem    REG  254,1   171800 1444564 /lib/x86_64-linux-gnu/libtinfo.so.5.9
irb      14 root  mem    REG  254,1   151120 1444515 /lib/x86_64-linux-gnu/libncurses.so.5.9
irb      14 root  mem    REG  254,1   297040 1444546 /lib/x86_64-linux-gnu/libreadline.so.6.3
irb      14 root  mem    REG  254,1   260648 3146915 /usr/local/lib/ruby/2.4.0/x86_64-linux/readline.so
irb      14 root  mem    REG  254,1   292976 3146919 /usr/local/lib/ruby/2.4.0/x86_64-linux/stringio.so
irb      14 root  mem    REG  254,1    33400 3146874 /usr/local/lib/ruby/2.4.0/x86_64-linux/enc/trans/transdb.so
irb      14 root  mem    REG  254,1   183168 3146831 /usr/local/lib/ruby/2.4.0/x86_64-linux/enc/encdb.so
irb      14 root  mem    REG  254,1  1738176 1444479 /lib/x86_64-linux-gnu/libc-2.19.so
irb      14 root  mem    REG  254,1  1051056 1444509 /lib/x86_64-linux-gnu/libm-2.19.so
irb      14 root  mem    REG  254,1    35176 1444487 /lib/x86_64-linux-gnu/libcrypt-2.19.so
irb      14 root  mem    REG  254,1    14664 1444492 /lib/x86_64-linux-gnu/libdl-2.19.so
irb      14 root  mem    REG  254,1   137384 1444543 /lib/x86_64-linux-gnu/libpthread-2.19.so
irb      14 root  mem    REG  254,1 15803280 3145980 /usr/local/lib/libruby.so.2.4.2
irb      14 root  mem    REG  254,1   140928 1444461 /lib/x86_64-linux-gnu/ld-2.19.so
irb      14 root    0u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    1u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    2u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    3r  FIFO   0,10      0t0   54293 pipe
irb      14 root    4w  FIFO   0,10      0t0   54293 pipe
irb      14 root    5r  FIFO   0,10      0t0   54294 pipe
irb      14 root    6w  FIFO   0,10      0t0   54294 pipe
irb      14 root    7u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    8u   CHR  136,0      0t0       3 /dev/pts/0
irb      14 root    9w   REG  254,1        0 3149355 /1
irb      14 root   10w   REG  254,1        0 3149365 /2
irb      14 root   11w   REG  254,1        0 3149369 /3
irb      14 root   12w   REG  254,1        0 3149372 /4
irb      14 root   13w   REG  254,1        0 3149422 /5
irb      14 root   14w   REG  254,1        0 3149423 /6
irb      14 root   15w   REG  254,1        0 3149425 /7
irb      14 root   16w   REG  254,1        0 3149455 /8
irb      14 root   17w   REG  254,1        0 3149457 /9
irb      14 root   18w   REG  254,1        0 3149458 /10
irb      14 root   19w   REG  254,1        0 3149459 /11
irb      14 root   20w   REG  254,1        0 3149460 /12
irb      14 root   21w   REG  254,1        0 3149461 /13
irb      14 root   22w   REG  254,1        0 3149462 /14
irb      14 root   23w   REG  254,1        0 3149463 /15
irb      14 root   24w   REG  254,1        0 3149464 /16
irb      14 root   25w   REG  254,1        0 3149465 /17
irb      14 root   26w   REG  254,1        0 3149466 /18
irb      14 root   27w   REG  254,1        0 3149467 /19
irb      14 root   28w   REG  254,1        0 3149468 /20
irb      14 root   29w   REG  254,1        0 3149469 /21
irb      14 root   30w   REG  254,1        0 3149470 /22
irb      14 root   31w   REG  254,1        0 3149471 /23
irb      14 root   32w   REG  254,1        0 3149472 /24
irb      14 root   33w   REG  254,1        0 3149473 /25
irb      14 root   34w   REG  254,1        0 3149474 /26
irb      14 root   35w   REG  254,1        0 3149475 /27
irb      14 root   36w   REG  254,1        0 3149476 /28
irb      14 root   37w   REG  254,1        0 3149477 /29
irb      14 root   38w   REG  254,1        0 3149478 /30
irb      14 root   39w   REG  254,1        0 3149479 /31
irb      14 root   40w   REG  254,1        0 3149480 /32
irb      14 root   41w   REG  254,1        0 3149481 /33
irb      14 root   42w   REG  254,1        0 3149482 /34
irb      14 root   43w   REG  254,1        0 3149483 /35
irb      14 root   44w   REG  254,1        0 3149484 /36
irb      14 root   45w   REG  254,1        0 3149485 /37
irb      14 root   46w   REG  254,1        0 3149486 /38
irb      14 root   47w   REG  254,1        0 3149487 /39
irb      14 root   48w   REG  254,1        0 3149488 /40
irb      14 root   49w   REG  254,1        0 3149489 /41
irb      14 root   50w   REG  254,1        0 3149490 /42
irb      14 root   51w   REG  254,1        0 3149491 /43
irb      14 root   52w   REG  254,1        0 3149492 /44
irb      14 root   53w   REG  254,1        0 3149493 /45
irb      14 root   54w   REG  254,1        0 3149494 /46
irb      14 root   55w   REG  254,1        0 3149495 /47
irb      14 root   56w   REG  254,1        0 3149496 /48
irb      14 root   57w   REG  254,1        0 3149497 /49
irb      14 root   58w   REG  254,1        0 3149498 /50
irb      14 root   59w   REG  254,1        0 3149499 /51
irb      14 root   60w   REG  254,1        0 3149500 /52
irb      14 root   61w   REG  254,1        0 3149501 /53
irb      14 root   62w   REG  254,1        0 3149502 /54
irb      14 root   63w   REG  254,1        0 3149503 /55

64個ファイルを開いていることが確認できました。

以上です。