lsof:オープンしているファイルを調べる

オープンしているファイルディスクリプタの調べ方を調査した。

lsof =list open files

lsof コマンドを利用すると、オープンされているファイルを調べることができる。実行には root 権限が必要。このコマンドは Linux にかかわらず多くの *nix 系OS に移植されている。

オープンファイルの一覧表示

# lsof | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 8,1 4096 2 /
init 1 root rtd DIR 8,1 4096 2 /
init 1 root txt REG 8,1 129800 7864383 /sbin/init
init 1 root mem REG 8,1 51712 3673673 /lib/libnss_files-2.11.1.so
init 1 root mem REG 8,1 43552 3673675 /lib/libnss_nis-2.11.1.so
init 1 root mem REG 8,1 97256 3673670 /lib/libnsl-2.11.1.so
init 1 root mem REG 8,1 35712 3673671 /lib/libnss_compat-2.11.1.so
init 1 root mem REG 8,1 1572232 3673664 /lib/libc-2.11.1.so
init 1 root mem REG 8,1 31744 3673680 /lib/librt-2.11.1.so

プロセス名で指定

# lsof -c apache2
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
apache2 13394 root cwd DIR 8,1 4096 2 /
apache2 13394 root rtd DIR 8,1 4096 2 /
apache2 13394 root txt REG 8,1 1482830 7471119 /usr/lib/apache2/mpm-worker/apache2
apache2 13394 root mem REG 8,1 51712 3673673 /lib/libnss_files-2.11.1.so
apache2 13394 root mem REG 8,1 43552 3673675 /lib/libnss_nis-2.11.1.so
...
apache2 16026 www-data DEL REG 0,4 9792925 /dev/zero
apache2 16026 www-data 0r CHR 1,3 0t0 904 /dev/null
apache2 16026 www-data 1w CHR 1,3 0t0 904 /dev/null
apache2 16026 www-data 2w REG 8,1 100 5770337 /var/log/apache2/error.log
apache2 16026 www-data 3u IPv4 9792913 0t0 TCP *:www (LISTEN)
apache2 16026 www-data 4r FIFO 0,8 0t0 9826894 pipe
apache2 16026 www-data 5w FIFO 0,8 0t0 9826894 pipe
apache2 16026 www-data 6w REG 8,1 0 5770463 /var/log/apache2/other_vhosts_access.log
apache2 16026 www-data 7w REG 8,1 0 5770797 /var/log/apache2/access.log
apache2 16026 www-data 8u 0000 0,9 0 877 anon_inode

PID で指定

# lsof -p `pgrep redis-server`

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
redis-ser 1125 jsmith cwd DIR 8,1 4096 4465842 /home/jsmith/dev/redis-2.4.8/src
redis-ser 1125 jsmith rtd DIR 8,1 4096 2 /
redis-ser 1125 jsmith txt REG 8,1 2792702 4466020 /home/jsmith/dev/redis-2.4.8/src/redis-server
redis-ser 1125 jsmith mem REG 8,1 1572232 3673664 /lib/libc-2.11.1.so
redis-ser 1125 jsmith mem REG 8,1 135745 3673678 /lib/libpthread-2.11.1.so
redis-ser 1125 jsmith mem REG 8,1 14696 3673667 /lib/libdl-2.11.1.so
redis-ser 1125 jsmith mem REG 8,1 534832 3673668 /lib/libm-2.11.1.so
redis-ser 1125 jsmith mem REG 8,1 136936 3673661 /lib/ld-2.11.1.so
redis-ser 1125 jsmith 0u CHR 136,5 0t0 8 /dev/pts/5
redis-ser 1125 jsmith 1u CHR 136,5 0t0 8 /dev/pts/5
redis-ser 1125 jsmith 2u CHR 136,5 0t0 8 /dev/pts/5
redis-ser 1125 jsmith 3u 0000 0,9 0 877 anon_inode
redis-ser 1125 jsmith 4u IPv4 10839259 0t0 TCP *:6379 (LISTEN)
redis-ser 1125 jsmith 5u IPv4 10839315 0t0 TCP localhost:6379->localhost:40023 (ESTABLISHED)

ポートで指定

# lsof -i:6379
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
redis-ser 1804 jsmith 4u IPv4 10845489 0t0 TCP *:6379 (LISTEN)
redis-ser 1804 jsmith 5u IPv4 10845593 0t0 TCP localhost:6379->localhost:46708 (ESTABLISHED)
redis-ser 1804 jsmith 6u IPv4 10845629 0t0 TCP localhost:6379->localhost:46709 (ESTABLISHED)
redis-cli 1812 jsmith 3u IPv4 10845592 0t0 TCP localhost:46708->localhost:6379 (ESTABLISHED)
redis-cli 1814 jsmith 3u IPv4 10845628 0t0 TCP localhost:46709->localhost:6379 (ESTABLISHED)

出力結果の確認

肝は FD(ファイルディスクリプタ) と TYPE。いくつかを例にとると

  • 3u unix → read-write fd で unix ドメインソケット
  • mem REG → メモリーマップファイルで、通常のファイル
  • rtd dir → ルートディレクトリ
  • 4u IPv4 → read/write の IPv4 socket
  • 2w REG → write only の通常ファイル
  • r FIFO → read only の FIFO

FD や TYPE の詳細は マニュアルを参照のこと

http://linux.die.net/man/8/lsof

ファイルディスクリプタの取得方法

プロセスごとの FD は /proc/{PID}/fd ディレクトリから情報を取得している。

# ll /proc/13394/fd
total 0
dr-x------ 2 root root 0 2012-02-25 12:42 ./
dr-xr-xr-x 7 root root 0 2012-02-18 15:07 ../
lr-x------ 1 root root 64 2012-02-25 12:42 0 -> /dev/null
l-wx------ 1 root root 64 2012-02-25 12:42 1 -> /dev/null
l-wx------ 1 root root 64 2012-02-25 12:42 2 -> /var/log/apache2/error.log
lrwx------ 1 root root 64 2012-02-25 12:42 3 -> socket:[9792913]
lr-x------ 1 root root 64 2012-02-25 12:42 4 -> pipe:[9826894]
l-wx------ 1 root root 64 2012-02-25 12:42 5 -> pipe:[9826894]
l-wx------ 1 root root 64 2012-02-25 12:42 6 -> /var/log/apache2/other_vhosts_access.log
l-wx------ 1 root root 64 2012-02-25 12:42 7 -> /var/log/apache2/access.log

ファイルディスクリプタの上限

プロセスごとのディスクリプタ上限はリソース RLIMIT_NOFILE で設定されている。

RLIMIT_NOFILE

Specifies a value one greater than the maximum file descriptor number that can be opened by this process. Attempts (open(2), pipe(2), dup(2), etc.) to exceed this limit yield the error EMFILE. (Historically, this limit was named RLIMIT_OFILE on BSD.)
http://www.kernel.org/doc/man-pages/online/pages/man2/getrlimit.2.html

大量のクライアントから Socket 接続されるサーバなどではこの上限を超えてしまい “Too many open files” というエラーを吐くことがたまにある。
そうした場合は、何がオープンされているのか lsof で調査し、場合によっては上限値を見直す必要がある。

上限値の変更
システムコールで変更するなら getrlimit/setrlimit 、シェルからだと bash 系では ulimit で設定変更可能。
変更例

$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
$ ulimit -n # only open files
1024

この上限値は

  • ソフトリミット(rlim_cur)
  • ハードリミット(rlim_max)

があり、 0<= rlim_cur <= rlim_max という上下関係がある。一般ユーザはソフトリミットしか変更できないようになっている。

システムのデフォルト値を変更

システムのデフォルト値を変更する場合、/etc/security/limits.conf ファイルを変更する。シンタックスは、ひだりから順に ドメイン、soft/hard 区分、リソース名、上限値

# vi /etc/security/limits.conf
add
* soft nofile 4096
* hard nofile 4096

実際に割り振られている上限値は /proc/{PID}/limits ファイルで確認できる。

# cat /proc/13394/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes unlimited unlimited processes
Max open files 1024 1024 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 16382 16382 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 20 20
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us

References

3 thoughts on “lsof:オープンしているファイルを調べる

Leave a comment