在CentOS系统中,每个用户和进程能够同时打开的文件数量是受到限制的,这个限制被称为“open files”或“file descriptor limit”,当运行高并发应用(如Nginx、MySQL、Redis等)时,默认的1024个文件打开上限往往过低,可能导致“Too many open files”错误,从而影响服务的稳定性和性能,了解并掌握如何正确修改这一限制至关重要。

理解文件描述符限制
在Linux系统中,一切皆文件,网络连接、管道、目录甚至普通文件,在内核层面都以文件描述符的形式存在,系统通过文件描述符来追踪和访问这些资源,限制打开文件的数量,本质上是为了防止单个进程或用户耗尽系统资源,从而保护整个系统的稳定。
这个限制分为两种:
- 软限制:当前生效的限制值,用户可以自行调整,但不能超过硬限制。
- 硬限制:系统设定的上限,只有root用户可以修改,普通用户只能将软限制提升到硬限制的值。
我们可以使用 ulimit 命令来查看和临时调整这些限制。
临时修改限制
临时修改是最快捷的方式,但仅对当前Shell会话及其子进程有效,一旦退出登录或关闭终端,设置便会失效。
查看当前的文件打开限制:
ulimit -n
这个命令会返回 1024。
要临时提升这个值,例如提升到 65536,可以执行:
ulimit -n 65536
再次执行 ulimit -n,你会发现返回值已经变成了 65536,这种方法非常适合用于快速测试或执行某项特定任务,但不适用于服务器服务的长期配置。
为特定用户永久修改
要让修改对特定用户永久生效,我们需要编辑 /etc/security/limits.conf 文件,这个文件由PAM(Pluggable Authentication Modules)模块在用户登录时读取并应用限制。
使用文本编辑器打开该文件:
sudo vi /etc/security/limits.conf
文件的格式为:<domain> <type> <item> <value>。
domain:可以是用户名、用户组名(组名前加),或通配符表示所有用户。type:soft(软限制)或hard(硬限制)。item:这里我们要设置的是nofile(number of open files)。value:要设置的数值。
要为用户 nginx 设置软限制和硬限制均为 65535,可以在文件末尾添加以下两行:

nginx soft nofile 65535 nginx hard nofile 65535
或者,要为所有用户设置一个统一的限制:
* soft nofile 65535 * hard nofile 65535
重要提示:修改此文件后,用户需要完全退出登录后重新登录,设置才能生效,对于已经运行的服务,需要重启服务。
为系统服务永久修改(推荐方法)
在现代的CentOS 7/8/9系统中,大多数服务由 systemd 管理。systemd 有自己的一套资源管理机制,它会忽略 /etc/security/limits.conf 中的设置,对于由 systemd 管理的服务,正确的做法是修改其服务单元文件。
最佳实践是使用 systemctl edit 命令创建一个覆盖配置,而不是直接修改原始文件,这样可以避免在系统软件包更新时丢失自定义配置。
以修改 nginx.service 为例:
-
创建覆盖配置:
sudo systemctl edit nginx.service
这会打开一个空的编辑器窗口。
-
添加限制配置: 在打开的编辑器中,输入以下内容,这里使用
LimitNOFILE来设置文件描述符限制。[Service] LimitNOFILE=65536
-
保存并退出: 保存文件后,
systemd会在/etc/systemd/system/nginx.service.d/目录下创建一个override.conf文件。 -
重新加载并重启服务:
sudo systemctl daemon-reload sudo systemctl restart nginx.service
-
验证配置: 可以使用以下命令检查服务是否成功应用了新限制:
systemctl show nginx.service | grep LimitNOFILE
输出应显示你设置的值,
LimitNOFILE=65536。
系统级全局文件句柄限制
除了 ulimit 这种针对用户/进程的限制外,系统还有一个全局的文件句柄总数限制,由内核参数 fs.file-max 控制。ulimit 的总和不应超过这个值。
查看当前全局限制:
cat /proc/sys/fs/file-max
如果服务器承载了大量并发连接,可能需要调高这个值,修改方法如下:
- 临时生效:
sudo sysctl -w fs.file-max=2097152
- 永久生效:
编辑
/etc/sysctl.conf文件,在末尾添加:fs.file-max = 2097152然后执行
sudo sysctl -p使配置立即生效。
只有当系统日志中出现 "VFS: file-max limit
不同修改方法对比
| 方法 | 作用范围 | 持久性 | 适用场景 |
|---|---|---|---|
ulimit -n |
当前Shell会话 | 临时 | 临时测试、调试 |
/etc/security/limits.conf |
指定用户或所有用户 | 永久(需重登录) | 用户级别的默认设置,非systemd服务 |
systemd Override |
指定systemd服务 | 永久(需重启服务) | 现代CentOS服务器首选方法,用于Nginx/MySQL等 |
sysctl.conf (fs.file-max) |
整个系统 | 永久(需重载) | 高负载服务器,全局资源调优 |
相关问答FAQs
问题1:我已经在 /etc/security/limits.conf 中修改了限制,并且也重新登录了,但为什么Nginx服务的文件打开限制还是1024?
解答: 这是因为您使用的CentOS版本(通常是7及以上)通过 systemd 来管理Nginx服务。systemd 在启动服务时,有自己独立的资源控制逻辑,它会绕过 limits.conf 文件,对于 systemd 管理的服务,您必须使用 systemctl edit <service_name>.service 的方法来创建一个覆盖片段,在其中设置 LimitNOFILE 参数,然后通过 systemctl daemon-reload 和 systemctl restart <service_name>.service 来应用更改,直接修改 limits.conf 对这类服务是无效的。
问题2:ulimit -n 和 fs.file-max 之间有什么关系?我应该先调整哪一个?
解答: fs.file-max 是一个内核级别的全局参数,它定义了整个操作系统所有进程可以打开的文件句柄总数,而 ulimit -n(或 LimitNOFILE)是一个针对单个用户或单个进程的限制,它规定了这一个“实体”最多能打开多少文件,它们的关系是:所有进程的文件描述符数量之和不能超过 fs.file-max,在实践中,您应该首先根据应用需求调整单个服务的 ulimit(或 LimitNOFILE),只有在系统日志报告达到 fs.file-max 限制,或者您预估系统中所有服务并发文件句柄总数会非常大时,才需要去调高 fs.file-max 这个全局上限,先调整服务限制,再考虑全局限制。