在多用户共享服务器(特别是科研服务器)上,有时某个用户运行了内存泄漏的 Python 或深度学习程序,导致整台服务器内存被吃满,其他人无法 SSH 登录。
本文记录一种系统级的用户内存限制方案,让每个用户最多只能使用系统内存的某个比例(例如 90%)。
🧠 一、基本原理:systemd user.slice
在使用 systemd 的 Linux 系统中(Ubuntu 18.04+ / CentOS 7+),每个登录用户都会被分配到独立的 slice (cgroup 组)。
路径一般为:
/sys/fs/cgroup/user.slice/user-<UID>.slice/
systemd 支持通过配置文件或命令限制每个 slice 的资源,比如:
MemoryMax:最大可用内存;CPUQuota:CPU 时间限制;IOWeight:I/O 优先级。
这样可以在用户层面聚合限制所有进程的总内存使用量。
⚙️ 二、配置步骤
1️⃣ 检查用户 slice 是否存在
先查看目标用户(如 hehf)的 slice 状态:
bash
systemctl status user-$(id -u hehf).slice
示例输出:
○ user-1002.slice - User Slice of UID 1002
Loaded: loaded
Drop-In: /usr/lib/systemd/system/user-.slice.d
└─10-defaults.conf
Active: inactive (dead)
说明该用户的 slice 存在,但当前没有活跃进程(inactive)。
2️⃣ 创建全局内存限制配置
创建 user-.slice.d 目录(注意中间有个 "-"):
bash
sudo mkdir -p /etc/systemd/system/user-.slice.d/
然后编辑配置文件:
bash
sudo nano /etc/systemd/system/user-.slice.d/90-memory.conf
写入以下内容(限制所有用户最多使用系统内存的 90%):
ini
[Slice]
MemoryMax=90%
3️⃣ 重新加载 systemd 配置
bash
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
这样配置会自动应用到所有新启动的 user.slice。
4️⃣ 验证配置是否加载
再次查看用户 slice:
bash
systemctl status user-$(id -u hehf).slice
此时应看到新增的 drop-in:
Drop-In: /usr/lib/systemd/system/user-.slice.d
└─10-defaults.conf
/etc/systemd/system/user-.slice.d
└─90-memory.conf
🧩 三、为什么是 inactive (dead)?
当输出中出现:
Active: inactive (dead)
说明该用户当前没有登录系统,也没有在后台运行进程。
只有当该用户登录系统或启动进程时,systemd 才会激活对应的 slice。
👉 解决方法:让目标用户登录一次,例如:
bash
ssh hehf@<服务器IP>
登录后再查看:
bash
systemctl status user-$(id -u hehf).slice
应该显示为:
● user-1002.slice - User Slice of UID 1002
Active: active since Sun 2025-10-26 22:34:05 CST; 1min ago
🧪 四、验证内存限制是否生效
确认 cgroup 路径存在:
bash
cat /sys/fs/cgroup/user.slice/user-$(id -u hehf).slice/memory.max
若返回类似:
96757023232
说明限制已生效(约 90GB ≈ 90% 内存)。
🧰 可选:为单个用户自定义上限
如果你希望为不同用户设置不同限制,例如:
bash
sudo systemctl set-property user-hehf.slice MemoryMax=60G
sudo systemctl set-property user-ps.slice MemoryMax=100G
即可针对性配置。
⚡ 五、测试脚本(触发内存限制)
切换到目标用户:
bash
sudo -u hehf bash
新建脚本 test_mem.py:
python
# test_mem.py
a = []
while True:
a.append(' ' * 10**7)
运行:
bash
python3 test_mem.py
当用户占用超过 MemoryMax 限额后,systemd 会自动终止该进程:
Memory cgroup out of memory: Killed process 12345 (python3)
🪄 六、常见问题与注意事项
| 问题 | 原因 | 解决方案 |
|---|---|---|
user-xxxx.slice inactive |
用户未登录 | SSH 登录一次激活 |
/sys/fs/cgroup/.../memory.max 不存在 |
cgroup 未挂载 | 登录后自动生成 |
| 只对 root 无效 | root 无限制 | 可单独配置 root.slice |
| 内存限制无效 | 未 reload systemd | 执行 systemctl daemon-reexec && systemctl daemon-reload |
📜 七、参考命令备查
bash
# 查看所有用户 slice
systemctl list-units --type=slice
# 查看单用户 slice 状态
systemctl status user-$(id -u username).slice
# 查看内存限制参数
systemctl show user-$(id -u username).slice | grep Memory
# 手动设置限制
sudo systemctl set-property user-username.slice MemoryMax=60G
🧭 八、总结
| 功能 | 命令 / 配置 |
|---|---|
| 全局限制所有用户内存上限 | /etc/systemd/system/user-.slice.d/90-memory.conf |
| 按用户单独限制 | systemctl set-property user-USERNAME.slice MemoryMax=XXG |
| 生效 | sudo systemctl daemon-reexec && sudo systemctl daemon-reload |
| 验证 | `systemctl show user-$(id -u USERNAME).slice |
✅ 最终效果:
- 每个普通用户最多只能使用系统总内存的 90%;
- 超过限制自动被 systemd 杀掉,不会拖垮整个服务器;
- 不影响 root 和系统服务。