Linux ulimit -n 改了却不生效:shell、服务单元 LimitNOFILE 与进程继承链
来源:17golang原创
时间:2026-08-28 02:51:38 187浏览 收藏
不少 Linux 服务故障不是参数没改,而是参数改在了错误的进程上:终端里执行 ulimit -n 65535 后,手工启动的程序能看到新值,由服务管理器拉起的同一个程序却仍然是旧值。原因在于 ulimit 修改的是当前 shell 的资源限制,子进程会沿着进程树继承;服务若由服务管理器启动,则应从服务单元的 LimitNOFILE 和实际 PID 复核。
排查“ulimit -n 不生效”时,先比较当前 shell 与目标服务的
/proc/PID/limits,再决定改 shell 配置、登录会话还是 systemd 单元;不要只看一个终端里的数字。
ulimit -n只改变当前 shell 的RLIMIT_NOFILE,不能直接改已经运行的其他服务。- 手工启动程序看父 shell 的限制,systemd 服务看单元配置和服务 PID 的实际限制。
LimitNOFILE=65535修改后要执行daemon-reload并重启目标服务,最后用/proc/PID/limits验收。- 软限制不能越过硬限制;提升硬限制需要足够权限,生产环境应保留回滚路径。
为什么同一台 Linux 机器会出现两个 ulimit -n
ulimit -n 展示的是当前 shell 的 open files 限制,本质对应 RLIMIT_NOFILE。它不是全机开关。shell 调整后,随后由该 shell 创建的子进程通常会继承这个限制;已经启动的服务不会被隔空刷新。
ulimit -Sn
ulimit -Hn
sh -c 'ulimit -Sn; ulimit -Hn'
前两行是当前 shell 的软、硬限制,第三行观察子 shell 是否继承。这里别急着修改 /etc/security/limits.conf,先确认目标程序究竟由谁启动。

先用 /proc/PID/limits 验收真正运行的进程
目标服务的限制要看目标 PID,而不是另开一个终端执行的 ulimit -n。假设服务名是 file-worker.service:
pid=$(systemctl show -p MainPID --value file-worker.service)
printf 'MainPID=%s\n' "$pid"
grep 'Max open files' "/proc/$pid/limits"
如果输出里的 soft limit 还是 1024,而你的终端是 65535,结论很明确:终端设置没有进入服务管理器的启动链。若 MainPID=0,说明服务当前没有运行,应先看 systemctl status file-worker.service。
| 观察位置 | 代表什么 | 适用场景 |
|---|---|---|
ulimit -Sn | 当前 shell 软限制 | 手工启动程序前 |
/proc/PID/limits | 目标进程实际限制 | 服务验收 |
systemctl show ... LimitNOFILE | systemd 单元设置 | 定位配置 |
服务单元要改 LimitNOFILE,而不是依赖终端环境
为服务创建 drop-in 配置:
sudo systemctl edit file-worker.service
[Service]
LimitNOFILE=65535
保存后按固定顺序让新配置进入服务启动流程:
sudo systemctl daemon-reload
sudo systemctl restart file-worker.service
systemctl show -p LimitNOFILE --value file-worker.service
pid=$(systemctl show -p MainPID --value file-worker.service)
grep 'Max open files' "/proc/$pid/limits"
验收要同时看到单元值为 65535,以及 /proc/$pid/limits 中 soft/hard 值符合预期。只看到 systemctl show 的数字还不够,因为最终资源限制属于实际进程。

旧配置为什么常常看起来改了却没生效
把当前 shell 当成全机配置
ulimit 是 shell 内建命令,写在一个终端里只影响该终端及其后代;由服务管理器启动的服务不以你的交互 shell 为父进程。
只改软限制,没有检查硬限制
用 ulimit -Sn 和 ulimit -Hn 一起看。非特权进程不能任意把软限制抬到硬限制以上。
改完单元文件却忘了重启
daemon-reload 让 systemd 重新读取单元,restart 才会让新限制进入新进程。
上线前保留一条可回滚的检查路径
如果程序实际打开的文件数远小于新上限,不要把 65535 当成必须值。先依据连接数、日志文件和监听套接字需求设定上限,并记录修改前后的 systemctl show 与 /proc/PID/limits 输出。回滚时删除 drop-in 中的 LimitNOFILE 覆盖项,重新执行 daemon-reload 和服务重启,再按同样的 PID 检查命令确认旧值恢复。
相关问题
为什么 sudo ulimit -n 65535 不好用?
sudo 会启动另一个命令上下文,不能替代在目标 shell 或服务管理器里配置资源限制。
修改 limits.conf 后要立刻重启服务吗?
通常需要让新的登录会话或对应会话管理链重新建立;由服务管理器启动的服务优先使用单元的 LimitNOFILE 并重启验证。
为什么 open files 还是不够?
比较 /proc/PID/fd 数量、错误日志中的 EMFILE 和 /proc/PID/limits 上限,再决定调参还是修复句柄关闭路径。
最后的验收清单
- 记录当前 shell 的 soft/hard 值。
- 确认服务由服务管理器还是手工命令启动。
- 检查
LimitNOFILE、执行daemon-reload和重启。 - 用实际
MainPID的/proc/PID/limits做最终验收。
-
426 收藏
-
387 收藏
-
242 收藏
-
238 收藏
-
402 收藏
-
400 收藏
-
118 收藏
-
329 收藏
-
文章 · linux | 13小时前 | 定时任务 · 任务调度 · linux运维 · 故障排查 · 服务管理 · Linux 定时任务 OnCalendar Persistent Linux 定时单元375 收藏
-
490 收藏
-
文章 · linux | 15小时前 | Linux · 日志排查 · journalctl · 服务管理器 · 故障定位 · Linux 时区 journalctl --since --until 日志时间窗口134 收藏
-
208 收藏
-
293 收藏
-
126 收藏
-
482 收藏
-
189 收藏
-
301 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习