cgexec 命令详解
更新时间:2026-09-17。本文是「一个命令一个文档」系列,聚焦
cgexec(control group exec,在控制组中执行)——容器与云原生命令族、libcgroup 套件。它是整条 cgroup 工作流的落点:cgcreate 建组、cgset 设限,cgexec负责把一个新进程放进组里跑。
cgexec 在启动目标命令的同时,把它的 PID 写进指定控制组的 tasks 文件,于是该进程及其后续 fork 出的子进程都受这个组的资源约束。它等价于「先启动进程、再把 PID echo 进 cgroup 任务文件」,但用一条命令原子完成。
一、基本用法
# 前置:建组 + 设限
cgcreate -g cpu,memory:batch
cgset -r cpu.cfs_quota_us=50000 -r memory.limit_in_bytes=512M batch
# 在组内运行命令(-g 控制器:组名 -- 命令)
cgexec -g cpu,memory:batch ./heavy-job.sh
cgexec -g cpu:batch -- stress -c 8 # 限 0.5 核跑压测,stress 也吃不满
cgexec -g memory:batch -- java -Xmx2g -jar app.jar # 内存超 512M 会被 OOM
cgexec -g cpu,memory:batch -sticky ./svc.sh # sticky:子进程留在同组
-g的控制器列表必须和建组时一致(或被其覆盖)。命令写在--之后,避免命令自己的参数被 cgexec 解析。验证是否真进组,用 cgget 看用量在涨,或直接cat /sys/fs/cgroup/memory/batch/tasks里有该 PID。
二、一条完整工作流
cgcreate -g cpu,memory:batch # 建组
cgset -r cpu.shares=256 batch # 低权重
cgset -r memory.limit_in_bytes=1073741824 batch
cgexec -g cpu,memory:batch ./batch-etl.sh & # 在限制中后台跑
cgget -g memory:batch | grep usage # 观察用量
cgdelete cpu,memory:batch # 进程结束后删组这正是"让某个批处理任务别和在线服务抢资源"的经典做法:在线服务留在默认组拿满资源,ETL/编译/压测丢进低 shares、有硬上限的组。容器在底层做的
docker run --cpus --memory,本质也是建组、设限、把容器 1 号进程放进组,只是由 runc 自动完成,背景见容器性能。
三、与 cgclassify 的区别:新进程 vs 已运行进程
| 命令 | 对象 | 典型场景 |
|---|---|---|
| cgexec | 尚未启动的进程,启动时即入组 | 从头就受限地跑一个任务 |
| cgclassify | 已经在运行的 PID,事后移入组 | 发现某进程在抢资源,临时把它挪走 |
已经跑起来的进程没法用 cgexec 回到过去,那是 cgclassify 的活。两者写入的都是组的
tasks(v1,写线程级)或cgroup.procs(写进程级)。
四、sticky 与子进程继承
默认情况下子进程跟随父进程留在同一 cgroup,所以 cgexec 起一个 shell、里面再派生一堆 worker,它们都在组里受约束。-sticky 用于配合 cgred(cgroup 规则守护):开启后即使有规则想把子进程按名字重新分类,也强制保留在当前组,避免任务"跑着跑着逃出限制"。
五、v2 与 systemd 等价做法
cgroup v2 下没有 cgexec,对已启动进程写 cgroup.procs,要"启动即入组"则交给 systemd:
# 手工:先在 v2 组里起 shell,再由该 shell 派生命令(子进程继承)
( echo $$ > /sys/fs/cgroup/batch/cgroup.procs; exec ./heavy-job.sh )
# 推荐:systemd-run 一步建 scope/unit 并设限、启动
systemd-run --user --scope --unit=batch -p CPUQuota=50% -p MemoryMax=512M ./heavy-job.sh
docker run --cpus=0.5 --memory=512m myimage ./heavy-job.sh # 容器场景相关命令
建组 cgcreate、设限 cgset、查看 cgget、移动已运行进程 cgclassify、列组 lscgroup。原理见容器性能与容器和虚拟机的区别。
总结
cgexec -g cpu,memory:组名 -- 命令 = 启动即放入 cgroup 受限运行:承接 cgcreate/cgset,把新进程写进组任务文件、子进程自动继承,是手动给任务套资源上限的落点;它管"新进程",已运行的进程用 cgclassify;v2/systemd 下等价为 systemd-run -p CPUQuota -p MemoryMax。