/proc/PID/fd
我试图理解为什么我会在进程的目录中看到成千上万个如下所示的新文件描述符java
:
$ sudo ls -lt /proc/585/fd | head
total 0
lr-x------ 1 crate crate 64 Jan 14 09:45 3036 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3037 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3038 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3035 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3032 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3033 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3034 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3028 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3029 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
这是来自 Debian GNU/Linux 服务器(版本 11.1)。此机器用作分布式数据库的节点之一(板条箱数据库, 版本4.6.6,用 Java 编程)。
sshfs
最近,我在该机器上安装了:
$ dpkg -l | egrep "(fuse)|(sshf)"
ii fuse3 3.10.3-2 amd64 Filesystem in Userspace (3.x version)
ii libfuse2:amd64 2.9.9-5 amd64 Filesystem in Userspace (library)
ii libfuse3-3:amd64 3.10.3-2 amd64 Filesystem in Userspace (library) (3.x version)
ii sshfs 3.7.1+repack-2 amd64 filesystem client based on SSH File Transfer Protocol
但我sshfs
安装该软件包后从未使用或配置过。换句话说,我没有通过sshfs
另一台服务器创建挂载等。
目前/etc/mtab
该服务器上有:
$ cat /etc/mtab | column -t
sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
udev /dev devtmpfs rw,nosuid,relatime,size=32885744k,nr_inodes=8221436,mode=755 0 0
devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
tmpfs /run tmpfs rw,nosuid,nodev,noexec,relatime,size=6580424k,mode=755 0 0
/dev/sda1 / ext4 rw,relatime,errors=remount-ro,stripe=256 0 0
securityfs /sys/kernel/security securityfs rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0
tmpfs /run/lock tmpfs rw,nosuid,nodev,noexec,relatime,size=5120k 0 0
cgroup2 /sys/fs/cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot 0 0
pstore /sys/fs/pstore pstore rw,nosuid,nodev,noexec,relatime 0 0
none /sys/fs/bpf bpf rw,nosuid,nodev,noexec,relatime,mode=700 0 0
systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=30,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=30739 0 0
mqueue /dev/mqueue mqueue rw,nosuid,nodev,noexec,relatime 0 0
tracefs /sys/kernel/tracing tracefs rw,nosuid,nodev,noexec,relatime 0 0
debugfs /sys/kernel/debug debugfs rw,nosuid,nodev,noexec,relatime 0 0
fusectl /sys/fs/fuse/connections fusectl rw,nosuid,nodev,noexec,relatime 0 0
hugetlbfs /dev/hugepages hugetlbfs rw,relatime,pagesize=2M 0 0
configfs /sys/kernel/config configfs rw,nosuid,nodev,noexec,relatime 0 0
/dev/sdb1 /data ext4 rw,relatime,stripe=256 0 0
tmpfs /run/user/1000 tmpfs rw,nosuid,nodev,relatime,size=6580420k,nr_inodes=1645105,mode=700,uid=1000,gid=1000 0 0
几天后,我在 CrateDB 系统的 Web UI 上遇到了“打开的文件太多”的情况。
最终,我重新启动该服务器,然后开始仔细监视它。
现在,当我检查具有最多文件描述符的进程时,我发现它是该java
进程:
$ sudo lsof +c 0 | awk '{ print $2 " " $1; }' | sort -rn | uniq -c | sort -rn | head -n5 | column -t
360126 585 java
136 558 rsyslogd
96 472 systemd-timesyn
87 1 systemd
61 3106 sshd
当我访问( )fd
的 PID 目录时,我看到最近创建的文件描述符如下:585
java
lr-x------ 1 crate crate 64 Jan 14 09:45 3036 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3037 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3038 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3035 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3032 -> /sys/fs/cgroup
cgroup
当我计算与或相关的文件描述符的数量时fuse
,我看到了数千个:
$ sudo ls -l /proc/585/fd | egrep "(cgroup)|(fuse)" | wc -l
2752
我还观察到文件描述符的数量因为java
(CrateDB) 进程开始增加当我与 CrateDB 的基于 Web 的管理 UI 交互时。
这文件描述符的数量相关cgroup
且sys-fs-fuse-connections.mount
持续增加。
我正在尝试理解这一点无限增长在数量上文件描述符与Java 进程相关cgroup
且针对 Java 进程。sys-fs-fuse-connections.mount
额外信息:我有另一组服务器在 Debian GNU/Linux(版本 10.x)上运行完全相同的 Java 应用程序 (CrateDB),它们没有sshfs
安装,这是主要区别。当我监视fd
Java 进程目录中的文件描述符时,我没有看到任何cgroup
相关sys-fs-fuse-connections.mount
的文件描述符,而且我从未遇到过“打开太多文件”的问题。
我不知何故怀疑这个问题不是由 CrateDB 直接引起的,而是由sshfs
和(可能是间接的?)fuse
引起的,因此我的问题是:我该如何测试这个问题?
更新(2022-02-17):我在新的 Debian GNU/Linux 11.2 虚拟机上测试了以下内容:
步骤1:通过 安装 CrateDB 的最新稳定版本 (4.7.0) apt
。CrateDB 使用的 Java 虚拟机报告如下:
$ /usr/share/crate/jdk/bin/java --version
openjdk 17.0.1 2021-10-19
OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12)
OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing)
第2步:列出打开文件数最多的进程:
echo -e "cntFiles PID Process Name" && echo "========================" && sudo lsof -e /run/user/1000/gvfs +c 0 | awk '{ print $2 " " $1; }' | sort -rn | uniq -c | sort -rn | head -n5
cntFiles PID Process Name
========================
7439 484 java
6876 1493 gnome-shell
1776 1799 gsd-xsettings
1566 1620 evolution-alarm
1463 1817 ibus-x11
然后启动strace
forjava
进程并关注该java
进程及其所有线程的相关内容/sys/fs/cgroup
:
$ sudo strace --decode-fds=all --trace-path=/sys/fs/cgroup --follow-forks --attach 484
strace: Process 484 attached with 37 threads
在此阶段,strace
不打印任何内容。
步骤3:运行 Firefox 并查看 CrateDB 管理 Web UI网址:http://localhost:4200/#!/
当我访问 CrateDB 的 Web 管理 UI 时,strace
开始报告很多!
$ sudo strace --decode-fds=all --trace-path=/sys/fs/cgroup --follow-forks --attach 484
strace: Process 484 attached with 37 threads
strace: Process 2697 attached
strace: Process 2698 attached
strace: Process 2699 attached
strace: Process 2700 attached
[pid 2698] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xc} ---
strace: Process 2701 attached
[pid 1325] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 1325] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 151</sys/fs/cgroup>
[pid 1325] dup(151</sys/fs/cgroup>) = 152</sys/fs/cgroup>
[pid 1325] fstat(151</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 1325] fcntl(151</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid 1325] fcntl(151</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid 1325] getdents64(151</sys/fs/cgroup>, 0x7f6e9c01bc90 /* 29 entries */, 32768) = 1112
[pid 2400] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 2400] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 155</sys/fs/cgroup>
[pid 2400] dup(155</sys/fs/cgroup>) = 156</sys/fs/cgroup>
[pid 2400] fstat(155</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 2400] fcntl(155</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid 2400] fcntl(155</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid 2400] getdents64(155</sys/fs/cgroup>, 0x7f6ec09507d0 /* 29 entries */, 32768) = 1112
[pid 1325] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 1325] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 159</sys/fs/cgroup>
[pid 1325] dup(159</sys/fs/cgroup>) = 162</sys/fs/cgroup>
[pid 1325] fstat(159</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 1325] fcntl(159</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid 1325] fcntl(159</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid 1325] getdents64(159</sys/fs/cgroup>, 0x7f6e9c02bd10 /* 29 entries */, 32768) = 1112
[pid 2400] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 2400] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 163</sys/fs/cgroup>
[pid 2400] dup(163</sys/fs/cgroup>) = 164</sys/fs/cgroup>
[pid 2400] fstat(163</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 2400] fcntl(163</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid 2400] fcntl(163</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid 2400] getdents64(163</sys/fs/cgroup>, 0x7f6ec0dd90e0 /* 29 entries */, 32768) = 1112
[pid 1325] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 1325] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 167</sys/fs/cgroup>
[pid 1325] dup(167</sys/fs/cgroup>) = 168</sys/fs/cgroup>
[pid 1325] fstat(167</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 1325] fcntl(167</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid 1325] fcntl(167</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid 1325] getdents64(167</sys/fs/cgroup>, 0x7f6e9c03bd90 /* 29 entries */, 32768) = 1112
[pid 2400] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 2400] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 171</sys/fs/cgroup>
[pid 2400] dup(171</sys/fs/cgroup>) = 172</sys/fs/cgroup>
[pid 2400] fstat(171</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 2400] fcntl(171</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid 2400] fcntl(171</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid 2400] getdents64(171</sys/fs/cgroup>, 0x7f6ec06baa20 /* 29 entries */, 32768) = 1112
[pid 1325] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 1325] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 175</sys/fs/cgroup>
[pid 1325] dup(175</sys/fs/cgroup>) = 176</sys/fs/cgroup>
[pid 1325] fstat(175</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 1325] fcntl(175</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid 1325] fcntl(175</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid 1325] getdents64(175</sys/fs/cgroup>, 0x7f6e9c04be10 /* 29 entries */, 32768) = 1112
[pid 2400] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 2400] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 179</sys/fs/cgroup>
[pid 2400] dup(179</sys/fs/cgroup>) = 180</sys/fs/cgroup>
[pid 2400] fstat(179</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid 2400] fcntl(179</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid 2400] fcntl(179</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid 2400] getdents64(179</sys/fs/cgroup>, 0x7f6ec15347f0 /* 29 entries */, 32768) = 1112
strace: Process 2738 attached
[pid 2738] +++ exited with 0 +++
strace: Process 2739 attached
[pid 2739] +++ exited with 0 +++
步骤4:我退出 Firefox,不再与 CrateDB 的 Web 管理 UI 进行交互,并立即strace
停止报告与 相关的任何内容/sys/fs/cgroup
。
步骤5:我检查了进程的打开文件数java
,现在这个数字是 8778。如果我继续使用 Web 管理 UI,这个数字就会无限增长。
答案1
显然,问题是不相关的或sshfs
,fuse
而是关于使用 CrateDB (用 Java 编写) 和 GNU/Linux 发行版的交互cgroup v2, 作为由 CrateDB 团队确定:
我们再次遇到了这个问题,最终可以将其归结为 CrateDB 与使用 cgroup v2 的发行版结合使用时的一个错误。修复程序已合并并已发布到版本 4.8.4 的测试渠道。我预计 5.0.2 很快就会发布。
更多详情请参阅: