我有一个 java 进程 (Glassfish),它正在泄漏文件描述符。我知道这一点,因为我得到了有用的java.io.IOException: Too many open files
异常。我可以查看/proc/PID#/fd
并查看所有打开的文件描述符。当我使用 lsof 时,我得到了大量这样的条目:
java 18510 root 8811u sock 0,4 1576079 无法识别协议
java 18510 root 8812u sock 0,4 1576111 无法识别协议
java 18510 root 8813u sock 0,4 1576150 无法识别协议
我看到每分钟有 12 个新文件被创建。我可以在 lsof 上使用哪些选项,或者我可以使用哪些其他工具来帮助追踪无法识别协议的套接字文件描述符?
答案1
查看使用进程最多的前 20 个文件句柄:
for x in `ps -eF| awk '{ print $2 }'`;do echo `ls /proc/$x/fd 2> /dev/null | wc -l` $x `cat /proc/$x/cmdline 2> /dev/null`;done | sort -n -r | head -n 20
输出格式为文件句柄计数、进程的 pid、命令行
示例输出
701 1216 /sbin/rsyslogd-n-c5
169 11835 postgres: spaceuser spaceschema [local] idle
164 13621 postgres: spaceuser spaceschema [local] idle
161 13622 postgres: spaceuser spaceschema [local] idle
161 13618 postgres: spaceuser spaceschema [local] idle
答案2
熟悉 strace 命令。它监视系统调用。我最近使用它来追踪导致 snmpd 守护进程反复崩溃的文件描述符泄漏。它需要一些时间来适应,但它是一个强大的工具。
您可以使用 strace 来附加到正在运行的进程(不要忘记使用 -f 标志来跟踪子进程)。
答案3
您到底想追踪什么?与泄露的 FD 相关的远程 IP 地址、有缺陷的代码,还是其他什么东西?
由于您已经确定存在泄漏,因此联系负责该 Java 流程的工程师似乎是合理的下一步。