将Python部署到服务上运行一段时间之后,总是会报下面的错误:
[Errno 24] Too many open files
增加文件描述符的限制
通常这个错误是因为系统达到了文件描述符的限制,可以使用ulimit -a
命令进行查看,结果如下:
real-time non-blocking time (microseconds, -R) unlimited
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 13143
max locked memory (kbytes, -l) 435188
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 13143
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
可以看到open files
的值是默认的1024。
临时增加限制
增加的方法很简单,可以使用 ulimit -Sn 65535
命令进行增,不过这种方式是临时增加,可以将上述命令加入到 /etc/rc.local
中实现系统启动自动设置。
永久增加限制
如果永久改变文件描述符的限制,需要编辑 /etc/security/limits.conf
文件,添加或修改下面的内容:
* soft nofile 65535
* hard nofile 65535
其中 soft nofile
是软限制,hard nofile
是硬限制。需要注销并重新登录系统才能生效。
修改完成之后可以再次使用ulimit -a
命令进行查看。
增加单个服务的文件描述符限制
上面这样修改之后,发现过一段时间还是频繁出现"Too many open files"的错误。因为Python程序是使用Gunicorn启动的,可以找到进程的id,然后使用 cat /proc/<PID>/limits
命令查看(其中 <PID>
是目标进程的ID):
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 13143 13143 processes
Max open files 1024 1024 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 13143 13143 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
从上面的结果可以看到服务进程的文件描述符限制依然是1024,可以修改服务的文件 (在 /etc/systemd/system/
目录下面,以 .service
结尾),在 [Service]
下面增加如下内容:
[Service]
LimitNOFILE=65535
重新加载systemd配置并重启服即可生效:
sudo systemctl daemon-reload
sudo systemctl restart <your-gunicorn-service>
通过以上设置基本上可以解决Too many open files的问题了。
另外需要指出的是,Ubuntu服务器默认是没有设置虚拟内存的,可以参考Azure Ubuntu服务器经常卡死的解决方法这篇文章进行设置。
参考资料:
Python Subprocess: Too Many Open Files
ubuntu下永久设置文件句柄数和虚拟内存,不需重启
net.ipv4.tcp_fin_timeout的错误理解
TCP连接状态详解及TIME_WAIT过多的解决方法