systemd-run --scope --memory-max=512M --unit=mytemp-job-$$ ./heavy-script.sh 是防止脚本失控最轻量、最干净的方式,自动创建cgroup v2作用域、绑定全部子进程、执行完自动清理,并集成日志与监控。

用 systemd-run 启动带内存限制的临时服务,是防止脚本失控最轻量、最干净的方式——它不改系统配置、不写 service 文件、不依赖持久化目录,执行完自动清理,适合运维巡检、CI/CD 任务、用户级批处理等场景。
直接运行带 MemoryMax 的临时服务
只需一条命令,就能为任意脚本启动一个受控的 systemd scope 单元:
systemd-run --scope --memory-max=512M --unit=mytemp-job-$$ ./heavy-script.sh-
--scope表示创建临时作用域(非长期 service),适合一次性任务 -
--memory-max=512M是物理内存硬上限,超限时进程会被 OOM Killer 终止(不会影响其他服务) -
--unit=...指定唯一单元名,便于后续查日志或手动干预;$$是当前 shell 进程号,确保不重名
配合超时与资源隔离更稳妥
单靠内存限制还不够:脚本可能卡在 IO、死循环不耗内存但占 CPU、或打开大量文件。建议组合使用:
- 加 CPU 时间限制:
--scope --memory-max=512M --cpu-quota=60%(限制平均 CPU 占用不超过 60%) - 加总运行时长:
--scope --memory-max=512M --runtime-max-sec=300(最多跑 5 分钟) - 限制文件句柄数:
--scope --memory-max=512M --property=LimitNOFILE=1024 - 禁止访问网络(如需沙箱):
--scope --memory-max=512M --property=NetworkNamespacePath=/proc/self/ns/net
验证与排错技巧
临时服务虽“即启即走”,但仍有迹可循:
- 查状态:
systemctl status mytemp-job-12345(单位名按你指定的来) - 看实时内存:
systemctl show mytemp-job-12345 -p MemoryCurrent -p MemoryMax - 查被杀原因:
journalctl -u mytemp-job-12345 -n 50 --no-pager,若含OOMKilled或Killed process就是内存超限触发 - 注意:普通用户默认无法设置
MemoryMax,需提前在/etc/systemd/logind.conf中设RestrictSessions=yes并重启systemd-logind,或由 root 授权sudo systemd-run ...
和 ulimit/cgroups 的关键区别
为什么优先选 systemd-run --scope 而不是 ulimit -v 或手建 cgroup?
-
ulimit -v只控虚拟地址空间,对现代 malloc/mmap 行为约束弱,且子进程继承后容易绕过 - 手动 cgroup 需挂载、建目录、写权限、记 PID、清理残留,操作繁琐易出错
-
systemd-run --scope自动创建完整 cgroup v2 层级、绑定所有子进程(含 fork 出的)、自动回收资源、集成 journal 日志、支持统一监控,是 systemd 原生推荐的轻量隔离方式











