ulimit -n 限制单个进程可打开的最大文件描述符数,仅作用于当前shell及子进程,需配合hard limit、/etc/security/limits.conf、systemd的limitnofile或sysctl的fs.file-max实现持久化与系统级防护。

在 Linux 中,ulimit -n 是限制单个进程可打开最大文件描述符(file descriptor,即“文件句柄”)数量的关键机制。由于网络连接、管道、普通文件等都占用文件描述符,若不设限,恶意或异常程序可能耗尽系统资源,导致其他服务无法建立新连接——这就是典型的“连接耗尽型拒绝服务(DoS)”。合理设置 ulimit -n 能有效缓解该风险。
理解 ulimit -n 的作用范围与局限
ulimit -n 设置的是**当前 shell 及其派生子进程**的软限制(soft limit),默认受硬限制(hard limit)约束。它只影响用户态进程,不直接控制内核全局句柄池(如 /proc/sys/fs/file-max)。这意味着:
- 仅对调用它的会话或启动的服务生效,systemd 服务需单独配置;
- 不能防止多个进程协同耗尽全局句柄,需配合系统级参数使用;
- 软限制可被进程自行提升(只要不超过硬限制),硬限制通常需 root 权限修改。
临时设置与验证方法
适用于调试或手动启动服务前快速加固:
- 查看当前限制:
ulimit -n(显示软限制),ulimit -Hn(显示硬限制); - 临时设为 1024:
ulimit -n 1024; - 验证是否生效:启动一个测试进程(如
sleep 300 &),再用ls /proc/$(pidof sleep)/fd | wc -l查看其已用句柄数,尝试ulimit -n 128后重复操作,确认上限被截断。
持久化配置常见场景
要让限制长期生效,需根据服务启动方式选择配置位置:
-
普通用户登录会话:编辑
/etc/security/limits.conf,添加如:
username soft nofile 1024
username hard nofile 2048
注意:需确保 PAM 模块pam_limits.so已启用(检查/etc/pam.d/common-session或对应登录配置); -
systemd 服务:在 service 文件中使用
LimitNOFILE=1024(软硬合一),例如:
[Service]
LimitNOFILE=1024
修改后运行systemctl daemon-reload && systemctl restart your-service; -
容器环境(如 Docker):启动时加参数
--ulimit nofile=1024:2048,或在 docker-compose.yml 中配置ulimits字段。
配合系统级参数形成纵深防御
单靠 ulimit 不足以完全防范 DoS,还需协同调整:
- 降低全局最大句柄数(防滥用):
echo 'fs.file-max = 65536' > /etc/sysctl.conf && sysctl -p; - 缩短连接超时,加速句柄回收:如 TCP 层设置
net.ipv4.tcp_fin_timeout = 30; - 监控关键指标:用
cat /proc/sys/fs/file-nr查看已分配/未使用/最大句柄数,结合 Prometheus + node_exporter 告警当使用率持续 >85%。











