ulimit -n修改无效是因为仅作用于当前shell及其子进程,且软限制不能超过硬限制;必须同步配置用户级(/etc/security/limits.conf+pam)、systemd级(limitnofile)和内核级(fs.file-max)三层限制,并重新登录或重载服务。

改不了,是因为只动了 ulimit -n —— 它只影响当前 shell 及其子进程,且软限制不能超过硬限制;真正要生效,必须同步调用户级、systemd 级、内核级三处参数。
ulimit -n 为什么设了 65536 还是 1024
不是命令错了,而是软限制被硬限制卡死。Linux 要求:ulimit -Sn(软限)≤ ulimit -Hn(硬限),而硬限默认由 PAM 在登录时加载,没配 /etc/security/limits.conf 就卡在 4096 或更低。
- 先查硬限:
ulimit -Hn,若输出是 4096,ulimit -n 65536必然失败 - 普通用户无法临时提硬限,必须写
/etc/security/limits.conf并重新登录(SSH 断开重连,不是新开终端) - root 用户也要显式写:
root soft nofile 65536和root hard nofile 65536,*不匹配 root - 确认
/etc/pam.d/common-session含session required pam_limits.so(Ubuntu/Debian 默认有;CentOS 需查/etc/pam.d/system-auth)
systemd 服务的 LimitNOFILE 怎么设才生效
nginx、redis、MySQL 这类用 systemctl start 启的服务,完全不读 /etc/security/limits.conf —— systemd 绕过了 PAM,改 limits.conf 对它们无效。
- 全局生效(推荐):
sudo systemctl edit --full systemd-system.conf,添加DefaultLimitNOFILE=65536 - 单服务生效(更安全):
sudo systemctl edit nginx.service,在[Service]段下加LimitNOFILE=65536 - 改完必须执行:
sudo systemctl daemon-reload,再sudo systemctl restart nginx - 验证是否生效:
cat /proc/$(pgrep nginx)/limits | grep "Max open files",看 Soft 和 Hard 是否已更新
fs.file-max 和 net.core.somaxconn 怎么协同调
只调进程级文件描述符还不够。一个连接要成功建立,得同时满足:进程有空闲 fd、系统总 fd 有余量、客户端能分配到可用端口、内核连接队列不溢出。
-
fs.file-max是系统总 fd 上限,设太小会导致所有进程抢资源。建议设为2097152,写入/etc/sysctl.conf后执行sudo sysctl -p -
net.ipv4.ip_local_port_range决定客户端可选端口数,默认32768 60999(约 2.8 万)。高并发短连接场景建议扩到1024 65535 -
net.core.somaxconn控制 listen backlog 队列长度,至少设为65535,否则新连接在进入 accept 队列前就被丢弃
最容易被忽略的是:MySQL 配了 max_connections = 1000 却只连到 300 就报错,问题不在 MySQL 配置,而在 systemd 给它的 LimitNOFILE 还是默认 1024 —— 扣掉日志、表文件、socket 等固定开销,实际能用于连接的 fd 远低于 1000。











