2026年6月21日 02:14

Linux ulimit 如何配置资源限制并排查常见问题?

Linux 里的 ulimit 用来限制一个 shell 以及它启动的子进程能使用多少系统资源。它最常见的用途,是防止某个程序打开太多文件、创建太多进程、占用过多栈空间,或者在崩溃时不生成 core 文件。

不过 ulimit 容易被误解:你在命令行里执行 ulimit -n 65535,只影响当前 shell 和它后面启动的进程;已经运行的服务不会自动改变;由 systemd 管理的服务,也不会因为你改了 /etc/security/limits.conf 就一定生效。

ulimit 到底限制什么?

ulimit 本质上是 shell 内置命令,用来查看或设置进程资源限制。最重要的两个概念是软限制和硬限制。

  • 软限制(soft limit):当前实际生效的限制,普通用户通常可以调低,也可以在不超过硬限制的前提下调高。
  • 硬限制(hard limit):软限制的上限,普通用户不能随便提高,通常需要 root 或具备相应权限的进程调整。
bash
ulimit -Sn # 查看 soft nofile ulimit -Hn # 查看 hard nofile ulimit -a # 查看全部限制

常用 ulimit 命令有哪些?

命令含义常见场景
ulimit -n最大打开文件数,等价于 nofileNginx、数据库、高并发连接
ulimit -u最大用户进程数,等价于 nproc防止进程或线程创建过多
ulimit -s栈大小,等价于 stack递归过深、线程栈配置
ulimit -ccore 文件大小,等价于 core程序崩溃排查
ulimit -l最大锁定内存,等价于 memlock数据库、DPDK、实时程序
ulimit -v最大虚拟内存限制进程虚拟地址空间
ulimit -t最大 CPU 时间限制 CPU 占用时间
ulimit -f最大文件大小防止写出超大文件

临时把最大打开文件数调到 65535:

bash
ulimit -n 65535

启用 core 文件:

bash
ulimit -c unlimited

这类命令只对当前 shell 和它之后启动的子进程有效。

nofile、nproc、stack、core、memlock 分别怎么用?

nofile 控制一个进程最多能打开多少文件描述符。这里的“文件”不只是普通文件,还包括 socket、pipe、epoll fd 等。Web 服务、网关、数据库经常需要调大它。连接数一高,最先遇到的往往就是 Too many open files

nproc 限制用户最多能拥有多少个进程。很多时候线程也会受到这个限制影响,所以 Java、Go、数据库或高并发程序创建线程失败时,也要检查它。

stack 控制进程线程栈大小。栈太小,递归深、局部变量大、线程模型复杂的程序可能崩溃;栈太大,又会让大量线程浪费地址空间。

core 控制程序崩溃时能否生成 core dump。core 文件还受系统 core_pattern、工作目录权限、磁盘空间、systemd-coredump 等因素影响,不能只看 ulimit -c

memlock 控制进程最多能锁定多少内存,数据库、实时计算、DPDK、Elasticsearch 某些配置会关注它。

limits.conf 的格式怎么写?

永久配置通常写到 /etc/security/limits.conf/etc/security/limits.d/*.conf

格式是:

conf
<domain> <type> <item> <value>

常见配置:

conf
* soft nofile 65535 * hard nofile 65535 username soft nproc 4096 username hard nproc 8192 @groupname soft memlock 1048576 @groupname hard memlock 2097152 * soft core unlimited * hard core unlimited

domain 可以是 *、用户名、@组名type 可以是 softhard-itemnofilenprocstackcorememlock 等;value 是限制值或 unlimited

生产环境里推荐把 soft、hard 分开写,便于排查到底哪个值没有生效。

为什么改了 limits.conf 还是没生效?

/etc/security/limits.conf 主要通过 PAM 的 pam_limits.so 在用户登录会话中生效。也就是说,它通常影响 SSH 登录、su、login 等 PAM 会话。

但 systemd 管理的服务不一定走这种登录链路。你改了 limits.conf,然后执行 systemctl restart nginx,Nginx 的限制值未必会变。systemd 服务应该用自己的配置方式。

systemd 服务如何设置 ulimit?

推荐用 drop-in 文件,不要直接改发行版自带的 service 文件。

bash
sudo systemctl edit nginx

写入:

ini
[Service] LimitNOFILE=65535 LimitNPROC=4096 LimitCORE=infinity LimitMEMLOCK=infinity

保存后执行:

bash
sudo systemctl daemon-reload sudo systemctl restart nginx

再查看实际进程限制:

bash
cat /proc/$(pidof nginx | awk '{print $1}')/limits

systemd 里常用 infinity 表示无限制,而 limits.conf 里常用 unlimited

如何查看正在运行进程的真实限制?

不要只看当前终端的 ulimit -a。它只能说明当前 shell 的限制,不能代表某个服务进程。

bash
cat /proc/PID/limits ls /proc/PID/fd | wc -l ps -eLf | grep PID | wc -l

如果要临时查看或调整某个已运行进程的限制,可以用 prlimit

bash
prlimit --pid PID prlimit --pid PID --nofile=65535:65535

prlimit 适合临时救急或验证问题,但生产配置还是应该落到 systemd drop-in、limits.d 或应用启动脚本里,避免重启后丢失。

fs.file-max 和 ulimit -n 是什么关系?

ulimit -n 控制的是单个进程的最大打开文件数。fs.file-max 控制的是整个系统层面的文件句柄上限。

bash
cat /proc/sys/fs/file-max cat /proc/sys/fs/file-nr sysctl -w fs.file-max=2097152

如果单个进程的 nofile 很小,会先撞到 Too many open files;如果系统整体文件句柄耗尽,多个进程都可能异常。两者不是一个层面的限制,排查时要分开看。

常见故障怎么排查?

遇到 Too many open files,先确认是哪一层不够:

bash
cat /proc/PID/limits | grep "open files" ls /proc/PID/fd | wc -l cat /proc/sys/fs/file-nr

如果进程 fd 数接近 Max open files,调大 nofile。如果是 systemd 服务,要配置 LimitNOFILE=,而不是只改当前 shell 的 ulimit -n

core 文件没有生成时,检查 ulimit -c/proc/PID/limits/proc/sys/kernel/core_pattern、目录权限和磁盘空间。

进程或线程创建失败时,重点看 nproc。内存相关报错还要一起检查系统内存、cgroup 限制、容器限制、swap、overcommit 策略。

配置 ulimit 的最佳实践

先看真实进程限制,优先用 /proc/PID/limits。区分临时和永久:命令行 ulimit 适合临时验证,长期配置要落到配置文件。区分登录用户和服务:PAM 登录会话看 limits.conf / limits.d,systemd 服务看 LimitNOFILE=LimitNPROC= 等 drop-in 配置。

不要盲目写 unlimitedcorememlocknofile 都可能影响系统稳定性或磁盘空间。配置完必须重启服务并用 /proc/PID/limits 确认,而不是相信配置文件已经生效。

简单记住一句话:ulimit 管的是进程资源上限;limits.conf 多数影响 PAM 登录会话;systemd 服务要用 Limit* 配置;排查时以 /proc/PID/limits 看到的值为准。

标签:Linux