オープンしているファイルディスクリプタの調べ方を調査した。
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
- MAN : GETRLIMIT(2)
http://www.kernel.org/doc/man-pages/online/pages/man2/getrlimit.2.html - IBM : Finding open files with lsof
http://www.ibm.com/developerworks/aix/library/au-lsof.html - MongoDB : Admin Zone > Troubleshooting > Too Many Open Files
http://www.mongodb.org/display/DOCS/Too+Many+Open+Files - A Quick Start for Lsof
http://www.opensource.apple.com/source/lsof/lsof-41/lsof/00QUICKSTART - Lsof FAQ(膨大)
ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ - Sun Developer Network : Solaris OS Solutions to 32-Bit stdio’s 256 File-Descriptors Limitation
http://developers.sun.com/solaris/articles/stdio_256.html
32 bit Solaris はファイルディスクリプターの上限が 256
3 thoughts on “lsof:オープンしているファイルを調べる”