前言

本人日常开发流程中常使用 PyCharm 中的 Remote Interpreter,其通过 SSH 连接到基于 systemD 的容器环境,长时间运行项目后会出现 OSError: [Errno 24] Too many open files

虽然这个问题一定程度上可能与业务代码有关,但默认限制允许单进程打开的文件数量(1024)属实也太低了,多线程场景下会超出限制也是常有的事情。

原因分析

docker-compose.yml 中,本人为开发环境所使用的容器定义了 ulimits,如下所示:

ulimits:
    nofile:
    soft: 32768
    hard: 32768

配置似乎没有问题,但通过 SSH 连接到容器查看 ulimit,得知限制仍是默认值(1024)

root@0b0ccef66ca2:~# ulimit -n
1024

于是进行了进一步排查,发现限制是从 sshd 进程开始附加的:

root@0b0ccef66ca2:~# ps ax|grep ssh
     58 ?        Ss     0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
     61 ?        Ss     0:00 sshd: root@pts/1
    106 pts/1    S+     0:00 grep --color=auto ssh
root@0b0ccef66ca2:~# cat /proc/58/limits |grep open
Max open files            32768                32768                files     
root@0b0ccef66ca2:~# cat /proc/61/limits |grep open
Max open files            1024                 1048576              files     
root@0b0ccef66ca2:~# 

由于 SSH 通过 PAM 进行用户认证,所以该限制很可能是由 PAM 模块默认配置附加的,最终影响到了ulimit。

解决方案

经过测试,确实与 SSH 的 PAM 配置有关,执行以下命令即可解除限制:

sed -i '/pam_limits.so/s/^/#/' /etc/pam.d/sshd
  • 补充:除了 PAM 的限制,还包含 systemD 的限制,还需要修改关于 systemD 的配置。
echo 'DefaultLimitNOFILE=32768' >> /etc/systemd/system.conf