前言
本人日常开发流程中常使用 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