`ulimit` 是 Shell 內建命令,用於控制進程可用的系統資源上限 (Resource Limits)。正確配置文件描述符數、進程數、棧大小、核心轉儲等限制,是高併發服務器、容器宿主機、數據庫節點穩定運行的基礎。本文詳細解析各參數含義、臨時/永久修改方法、systemd 整合與常見踩坑。
| 選項 | 資源 | 單位 | 默認值 (典型) | 建議高併發值 | 說明 |
|---|---|---|---|---|---|
| -n | 最大打開文件描述符數 | 個 | 1024 | 65535 / 1000000 | **最關鍵參數**,含 Socket、文件、管道 |
| -u | 最大用戶進程數 (含線程) | 個 | 3846 / 无限制 | 65535 / 1000000 | 防止 fork 炸彈,Nginx/Go/Java 線程池受限 |
| -s | 棧大小 | KB | 8192 (8MB) | 256-1024 (KB) | 線程棧,過大限制線程數,過小導致棧溢出 |
| -c | Core Dump 文件最大值 | 塊 (512B) / 0=禁用 | 0 | unlimited | 生產環境建議開啟並配合目錄權限 |
| -f | Shell 創建文件最大值 | 塊 (512B) | unlimited | unlimited | 極少調整 |
| -t | CPU 時間上限 | 秒 | unlimited | unlimited | 防止失控進程佔用 CPU |
| -v | 虛擬內存上限 | KB | unlimited | 視業務而定 | 容器/沙箱限制記憶體 |
| -m | 常駐內存上限 | KB | unlimited | 通常不生效 (Linux 忽略) | 建議用 cgroups memory.limit_in_bytes |
| -l | 最大鎖定內存 | KB | 64 / 无限制 | unlimited | mlock()、大頁內存、實時系統關鍵 |
| -p | 管道緩衝區大小 | 512B 塊 | 8 | 默認即可 | |
| -r | 實時調度優先級上限 | 優先級值 | 0 | 99 | SCHED_FIFO/RR 需 CAP_SYS_NICE |
# 查看所有限制 (软限制)
ulimit -a
# 查看硬限制
ulimit -Ha
# 查看單項
ulimit -n # 软限制
ulimit -Hn # 硬限制
# 臨時修改 (僅當前 Shell 及其子進程生效)
ulimit -n 65535
ulimit -u 65535
ulimit -c unlimited
# 同時設置软/硬限制 (-S 软, -H 硬, 默認雙設置)
ulimit -SHn 65535
注意:软限制 ≤ 硬限制;普通用戶可降低软限制、不可超過硬限制;root 可任意設置。
# 格式: -
# * 代表所有用戶,root 需單獨寫
* soft nofile 655350
* hard nofile 655350
* soft nproc 11000
* hard nproc 11000
root soft nofile 655350
root hard nofile 655350
root soft nproc 11000
root hard nproc 11000
# 啟用 core dump
* soft core unlimited
* hard core unlimited
需確保 `/etc/pam.d/login`、`/etc/pam.d/sshd`、`/etc/pam.d/su` 包含:
session required pam_limits.so
# /etc/systemd/system/your-service.service.d/limits.conf
[Service]
LimitNOFILE=655350
LimitNPROC=11000
LimitCORE=infinity
LimitMEMLOCK=infinity
LimitSTACK=1048576 # 1MB (單位 bytes)
# 重載並重啟
systemctl daemon-reload
systemctl restart your-service
**優先級**:systemd 服務配置 > limits.conf > 默認值。容器中 systemd 通常不運行,需在容器運行時參數或入口腳本設置。
ulimit -SHn 655350
ulimit -SHu 11000
ulimit -c unlimited
# 文件描述符系統總上限
fs.file-max = 2097152
fs.nr_open = 1048576 # 單進程硬上限上限 (kernel 2.6.25+)
# 生效
sysctl -p
單進程 `ulimit -n` 不能超過 `fs.nr_open`。
# 1. 確認當前進程限制
cat /proc/$$/limits
# 2. 確認指定 PID 進程限制
cat /proc//limits
# 3. 實時監控文件描述符使用
watch -n 1 'lsof -p | wc -l'
# 4. 系統全局 FD 使用
cat /proc/sys/fs/file-nr
# 輸出:已分配FD數 已分配但未使用 系統最大FD數
| 現象 | 原因 | 解決 |
|---|---|---|
| ulimit -n 修改後重啟失效 | 未寫入 limits.conf 或 pam_limits.so 未載入 | 檢查 /etc/pam.d/* 包含 session required pam_limits.so |
| systemd 服務不生效 limits.conf | systemd 讀取自身 LimitNOFILE | 使用 systemd drop-in 配置 LimitNOFILE |
| 普通用戶無法提高硬限制 | 硬限制需 root 權限 | 在 limits.conf 由 root 預設 |
| Java 應用報 "Too many open files" | JVM 默認使用 ulimit -n,但 Netty 等可能預分配 | 啟動腳本加 ulimit -n;JVM 參數 -XX:-MaxFDLimit |
| core 文件不生成 | ulimit -c 0 或目錄無寫權限 / kernel.core_pattern 導向管道 | ulimit -c unlimited;mkdir -m 1777 /var/crash;sysctl kernel.core_pattern=/var/crash/core.%e.%p |
| 棧大小設置過小導致 Segfault | ulimit -s 64 (64KB) 不足 | 線程棧建議 256KB-1MB (ulimit -s 256-1024) |
#!/bin/bash
# /usr/local/sbin/optimize-limits.sh
cat > /etc/security/limits.d/99-optimize.conf <<'EOF'
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 1048576
* hard nproc 1048576
* soft core unlimited
* hard core unlimited
* soft memlock unlimited
* hard memlock unlimited
root soft nofile 1048576
root hard nofile 1048576
root soft nproc 1048576
root hard nproc 1048576
root soft core unlimited
root hard core unlimited
root soft memlock unlimited
root hard memlock unlimited
EOF
cat > /etc/sysctl.d/99-fs-limits.conf <<'EOF'
fs.file-max = 2097152
fs.nr_open = 1048576
vm.max_map_count = 262144
EOF
sysctl --system
systemctl daemon-reload
echo "優化完成,請重新登入或重啟服務驗證。"
資源限制是系統穩定性的「安全閥」。生產環境建議採用 **limits.conf (用戶登入) + systemd drop-in (服務級) + sysctl fs.nr_open (內核上限)** 三層配置,並納入自動化部署流程。定期用 `cat /proc/