用 systemd-run 临时限制脚本内存与 CPU,避免拖垮系统

举报
yd_246123679 发表于 2026/10/26 00:15:54 2026/10/26
【摘要】 面对可能内存泄漏的脚本,直接用 systemd-run 创建临时 cgroup,设置 MemoryMax 与 CPUQuota 运行,再用 systemd-cgtop 观察限制是否生效,可在不修改持久配置的情况下防止单个进程耗尽系统资源。

用 systemd-run 临时限制脚本资源

问题场景

在开发或运维中,经常需要运行一些来源不确定、可能内存泄漏或吃满 CPU 的脚本。例如一个批量处理数据的临时脚本,或者第三方提供的工具。如果直接在前台或后台运行,它可能不断申请内存,最终触发系统 OOM,把重要服务一起拖垮。永久修改 systemd 服务或 cgroup 配置又太重,且不适合一次性任务。此时可以用 systemd-run 创建临时 cgroup,给进程套上资源限额,用完即走。

解决思路

systemd-run 可以启动一个 transient unit(临时服务或 scope),并通过 -p 传入资源控制属性。常用的两个属性:

  • MemoryMax=512M:硬内存上限,超过后 cgroup 内进程可能被 OOM killer 终止。
  • CPUQuota=50%:CPU 配额,表示最多使用半个 CPU 核心的计算时间。

这两个属性由 systemd 的资源控制框架管理,底层是 cgroup。运行后可以用 systemd-cgtop 按内存或 CPU 查看各 cgroup 的实时占用,确认限制是否生效。

最小可运行示例

先准备一个会持续申请内存的 Python 脚本,保存为 /tmp/leak_demo.py。示例仅用于演示,请勿在生产环境随意执行:

# /tmp/leak_demo.py
import time

chunks = []
while True:
    chunks.append(bytearray(10 * 1024 * 1024))  # 每次申请 10 MiB
    time.sleep(0.1)

这个脚本会不断向列表里追加 10 MiB 的字节数组,内存占用持续上升。

用 systemd-run 启动它,并加上 512M 内存和 50% CPU 限制:

sudo systemd-run --unit=leak-demo -p MemoryMax=512M -p CPUQuota=50% python3 /tmp/leak_demo.py

如果当前用户已有 systemd user manager,也可以尝试 systemd-run --user,但资源控制属性是否可用取决于系统配置。没有 sudo 权限时请先确认权限边界。

启动后,unit 会在后台运行。查看状态:

systemctl status leak-demo

查看 cgroup 资源限制是否写入:

systemctl show leak-demo -p MemoryMax -p CPUQuota

预期能看到 MemoryMax=536870912(512M 的字节数)和 CPUQuota=50% 之类的输出。注意不同 systemd 版本显示格式可能不同。

用 systemd-cgtop 验证

运行:

systemd-cgtop --order=memory

或者直接运行 systemd-cgtop,然后观察 leak-demo 对应的 cgroup。按内存排序时,应该能看到它的内存占用逐渐上升,接近 512M 后不再明显增长;随后进程可能因超过硬限制被 OOM killer 终止。此时再执行:

systemctl status leak-demo

可能会看到 unit 进入 failed 状态,并提示被信号杀死或内存超限。也可以观察 CPU 列,确认它最多只消耗约一半核心的 CPU 时间。

如果只是想验证限制是否生效,而不希望进程被杀,可以先用 MemoryHigh 代替 MemoryMax,或者把脚本改成有限循环。但 MemoryHigh 是软限制,达到后主要触发回收和节流,不保证一定杀死进程。

运行方法与清理

如果 unit 还在运行,可以停止:

sudo systemctl stop leak-demo

对于 transient unit,停止后通常会自动清理。若需要彻底删除,可以:

sudo systemctl reset-failed leak-demo

边界与限制

  1. 环境依赖:systemd-run、systemd-cgtop 需要 Linux 上运行 systemd。容器、WSL、部分精简系统可能没有完整 systemd,命令会不可用。
  2. cgroup 版本:cgroup v1 与 v2 对控制器的支持不同。MemoryMax 和 CPUQuota 要求对应控制器已启用;如果属性不生效,需要检查内核启动参数和 systemd 配置。
  3. 权限:通常需要 root 或具备相应 polkit 权限。普通用户使用 --user 时,资源限制能力可能受限。
  4. 进程行为:cgroup 会包含子进程,但如果脚本主动脱离 cgroup、创建新 session 或通过其他机制逃逸,限制可能失效。不要用它来约束恶意程序。
  5. OOM 影响:MemoryMax 是硬限制,超限会触发 OOM killer,可能杀死 unit 内进程。测试时不要在生产核心业务上直接使用。
  6. 参数占位:示例中的 512M、50%、脚本路径和 unit 名称都是占位值,请按实际需求调整。
  7. 临时性:systemd-run 创建的 unit 默认不持久化,重启后不会保留。如果需要长期限制,应编写正式的 unit 文件或 drop-in 配置。

小结

对于一次性、可能失控的脚本,systemd-run 提供了一种轻量的资源隔离方式:用 -p MemoryMax 和 -p CPUQuota 设置上限,再用 systemd-cgtop 观察实际占用。它不能替代完善的资源规划和监控,但在开发、测试和临时任务中可以有效降低单个进程拖垮系统的风险。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。