为什么 xinetd 在启动时尝试关闭文件描述符?

为什么 xinetd 在启动时尝试关闭文件描述符?

我已经在主机上的xinetddocker 容器(基础映像centos:7)内运行。rockylinux 9

xinetd在 docker 镜像中启动服务时,它似乎挂起了。所以我使用了strace,并发现以下输出,快速计数:

close(181189)                           = -1 EBADF (Bad file descriptor)
close(181190)                           = -1 EBADF (Bad file descriptor)
close(181191)                           = -1 EBADF (Bad file descriptor)
close(181192)                           = -1 EBADF (Bad file descriptor)
close(181193)                           = -1 EBADF (Bad file descriptor)
close(181194)                           = -1 EBADF (Bad file descriptor)
close(181195)                           = -1 EBADF (Bad file descriptor)
close(181196)                           = -1 EBADF (Bad file descriptor)

strace xinetd在另一台主机上运行Centos 8我看到了同样的行为。

看起来它xinetd正在遍历所有可用的文件描述符,超过/proc/sys/fs/file-max(如果配置了限制,它会超过该限制)直到数字用完。

这是怎么回事?为什么会出现这种行为?

2023 年 3 月更新:

对于有类似情况的人,根据下面详细的答案,你可以设置通过 docker 实现 ulimits运行容器时。这在docker compose,并且在游牧民族。不幸的是,在 k8s 中不可用

答案1

许多传统守护进程都会这样做,作为其“守护进程化”序列的一部分,旨在避免从用户环境中继承任何东西,因为传统上(在面向 IPC 的 init 系统(如 systemd 或 Upstart)流行之前)管理员会直接从交互式会话中运行 /etc/rc.d 脚本,有时只会直接启动守护进程二进制文件 - 然后应该分叉/双分叉,重新打开 stdin/out/err,摆脱任何控制 tty,编写自己的 pid 文件,等等。

例如,旧的 /etc/rc.d/inetd 可能像这样简单:

case $1 in
    start)
        echo -n "Starting inetd..."
        /sbin/inetd
        echo "done."
[...]

但没有跨平台的方法来确定哪个文件描述符已打开。一些 Unix 具有诸如 closefrom() 之类的系统调用,其他 Unix 允许进程迭代 /proc/self/fd/[0-9],但有些 Unix 没有比从 3 一直迭代到当前 RLIMIT_NOFILE 值并盲目尝试每个可能的 FD 更好的方法。

后者就是 xinetd 所做的,假设它的 NOFILE 限制最多在 1k 到 4k 左右。(20-30 年前编写启动代码时通常就是这种情况 - 从那时起它就没有发生过太大的变化。)

相关内容