当前位置: 首页 > news >正文

Linux通过cgroups限制进程的cpu、内存使用率

脚本内容

一、

ubuntu@ccpp:~/lihuiqin/oci_oracle$ ./linux_cgroups_v2.sh===Kernel 编译脚本启动(tinyconfig + 资源限制)======设置 cgroup 资源限制===tee: /sys/fs/cgroup/kernel_limit/cpu.max: Permission denied

是因为这一句:

echo"${QUOTA_US}${PERIOD_US}"|sudotee"${CGROUP_PATH}/cpu.max">/dev/null

正常情况下,cgroup v2 的:

/sys/fs/cgroup/kernel_limit/cpu.max

是可以反复写的。

我运行下面的命令:

ubuntu@ccpp:~/lihuiqin/oci_oracle$cat/sys/fs/cgroup/kernel_limit/cgroup.procs#只查看目录本身信息,不显示里面的文件ubuntu@ccpp:~/lihuiqin/oci_oracle$ls-ld/sys/fs/cgroup/kernel_limit drwxr-xr-x2root root0May1116:53 /sys/fs/cgroup/kernel_limit

从这两个输出看:

cat/sys/fs/cgroup/kernel_limit/cgroup.procs

是空的,说明这个 cgroup 里没有残留进程

drwxr-xr-x2root root0May1116:53 /sys/fs/cgroup/kernel_limit

说明目录确实存在,属主是 root,这也正常。

所以结论是:

不是因为上次 make 进程残留导致 cpu.max 不能写。

更可能的原因是:/sys/fs/cgroup/kernel_limit/cpu.max这个文件本身不存在,原因通常是父 cgroup 没有启用 cpu controller
cpu.max不存在时,sudo tee会尝试“创建”这个文件,但 cgroupfs 不允许用户创建控制文件,于是就报:

Permission denied

你先检查一下 cpu.max 是否存在

运行:

ls-l/sys/fs/cgroup/kernel_limit

重点看里面有没有:

cpu.max memory.max memory.swap.max

如果没有cpu.max,那就基本确定是父级没有启用cpucontroller。


再检查父级 controller 状态

运行:

cat/sys/fs/cgroup/cgroup.controllerscat/sys/fs/cgroup/cgroup.subtree_control

你大概率会看到第一行有:

cpuset cpu io memory hugetlb pids rdma misc

但是第二行可能没有:

+cpu +memory

或者至少没有cpu


你现在这个情况的判断

根据你贴的结果:

cgroup.procs 是空的 kernel_limit 目录存在

所以不是 make 没清理干净。

最可能是这个:

/sys/fs/cgroup/kernel_limit/cpu.max

还没生成,因为父级没有启用 cpu controller。

你可以直接运行:

ls-l/sys/fs/cgroup/kernel_limit/cpu.max

如果返回:

No such file or directory

那就完全对上了。


如果启用 controller 也失败

如果执行:

echo'+cpu'>/sys/fs/cgroup/cgroup.subtree_control

也失败,那就说明 Ubuntu/systemd 对根 cgroup 管理比较严格。
这种情况下建议直接改用:

systemd-run--scope

也就是不用自己写/sys/fs/cgroup/kernel_limit/cpu.max,由 systemd 创建和管理 cgroup。这个在 Ubuntu 上通常更省心。

二、

1,查看kernel_limit目录内容

ubuntu@ccpp:~/lihuiqin/oci_oracle$ls-l/sys/fs/cgroup/kernel_limit total0-r--r--r--1root root0May1115:49 cgroup.controllers -r--r--r--1root root0May1115:49 cgroup.events -rw-r--r--1root root0May1115:49 cgroup.freeze --w-------1root root0May1115:49 cgroup.kill -rw-r--r--1root root0May1115:49 cgroup.max.depth -rw-r--r--1root root0May1115:49 cgroup.max.descendants -rw-r--r--1root root0May1115:49 cgroup.pressure -rw-r--r--1root root0May1116:54 cgroup.procs -r--r--r--1root root0May1115:49 cgroup.stat -rw-r--r--1root root0May1115:49 cgroup.subtree_control -rw-r--r--1root root0May1115:49 cgroup.threads -rw-r--r--1root root0May1115:49 cgroup.type -rw-r--r--1root root0May1115:49 cpu.pressure -r--r--r--1root root0May1115:49 cpu.stat -r--r--r--1root root0May1115:49 cpu.stat.local -rw-r--r--1root root0May1115:49 io.pressure -r--r--r--1root root0May1115:49 memory.current -r--r--r--1root root0May1115:49 memory.events -r--r--r--1root root0May1115:49 memory.events.local -rw-r--r--1root root0May1115:49 memory.high -rw-r--r--1root root0May1115:49 memory.low -rw-r--r--1root root0May1116:53 memory.max -rw-r--r--1root root0May1115:49 memory.min -r--r--r--1root root0May1115:49 memory.numa_stat -rw-r--r--1root root0May1115:49 memory.oom.group -r--r--r--1root root0May1115:49 memory.peak -rw-r--r--1root root0May1115:49 memory.pressure --w-------1root root0May1115:49 memory.reclaim -r--r--r--1root root0May1115:49 memory.stat -r--r--r--1root root0May1115:49 memory.swap.current -r--r--r--1root root0May1115:49 memory.swap.events -rw-r--r--1root root0May1115:49 memory.swap.high -rw-r--r--1root root0May1116:53 memory.swap.max -r--r--r--1root root0May1115:49 memory.swap.peak -r--r--r--1root root0May1115:49 memory.zswap.current -rw-r--r--1root root0May1115:49 memory.zswap.max -rw-r--r--1root root0May1115:49 memory.zswap.writeback -r--r--r--1root root0May1115:49 pids.current -r--r--r--1root root0May1115:49 pids.events -rw-r--r--1root root0May1115:49 pids.max -r--r--r--1root root0May1115:49 pids.peak

2,目录里面确实缺少 cpu.max

这个输出已经把原因基本定位了:

结论

/sys/fs/cgroup/kernel_limit/里面没有cpu.max文件

你现在目录里有:

cpu.pressure cpu.stat cpu.stat.local

但是没有:

cpu.max cpu.weight cpu.uclamp.min cpu.uclamp.max

所以之前这句:

echo"${QUOTA_US}${PERIOD_US}"|sudotee"${CGROUP_PATH}/cpu.max"

实际上是在尝试写一个不存在的 cgroup 控制文件。
cgroupfs 不允许你手动创建cpu.max,所以报:

Permission denied

不是因为你第二次写入被拒绝,也不是因为里面有残留进程。


根本原因

你的kernel_limit子 cgroup 里面有memory.maxmemory.swap.max,说明memory controller 已经可用

但是没有cpu.max,说明:

父级 cgroup 没有启用cpucontroller 给子 cgroup 使用。

也就是/sys/fs/cgroup/cgroup.subtree_control里面大概率没有:

+cpu

你现在先运行这两个命令看一下

cat/sys/fs/cgroup/cgroup.controllerscat/sys/fs/cgroup/cgroup.subtree_control

如果第一行有:

cpu

但第二行没有:

cpu

那就说明 CPU controller 存在,但没有启用给子 cgroup。


三、

1,查看cgroup下的controllers和subtree_control
ubuntu@ccpp:~/lihuiqin/oci_oracle$cat/sys/fs/cgroup/cgroup.controllers cpuset cpu io memory hugetlb pids rdma misc ubuntu@ccpp:~/lihuiqin/oci_oracle$cat/sys/fs/cgroup/cgroup.subtree_control memory pids
2,定位问题:cgroup没有把 cpu 下放给 /sys/fs/cgroup/kernel_limit;
cat/sys/fs/cgroup/cgroup.controllers cpuset cpu io memory hugetlb pids rdma misccat/sys/fs/cgroup/cgroup.subtree_control memory pids

意思是:

  • 系统支持cpucontroller;
  • 但当前根 cgroup 只把memorypids下放给子 cgroup;
  • 没有把cpu下放给/sys/fs/cgroup/kernel_limit
  • 所以你的kernel_limit目录里没有cpu.max
  • 因此写/sys/fs/cgroup/kernel_limit/cpu.max会失败。

先试这个修复命令

直接运行:

sudosh-c' echo "+cpu" > /sys/fs/cgroup/cgroup.subtree_control cat /sys/fs/cgroup/cgroup.subtree_control ls -l /sys/fs/cgroup/kernel_limit/cpu.max '

如果成功,你应该看到:

memory pids cpu

或者类似:

cpu memory pids

然后:

/sys/fs/cgroup/kernel_limit/cpu.max

应该存在。

接着测试写入:

sudosh-c'echo "20000 100000" > /sys/fs/cgroup/kernel_limit/cpu.max'cat/sys/fs/cgroup/kernel_limit/cpu.max

如果显示:

20000 100000

就说明 CPU 限制可以正常用了。


四、

1,添加cpu到subtree_control
ubuntu@ccpp:~/lihuiqin/oci_oracle$sudosh-c' echo "+cpu" > /sys/fs/cgroup/cgroup.subtree_control cat /sys/fs/cgroup/cgroup.subtree_control ls -l /sys/fs/cgroup/kernel_limit/cpu.max 'cpu memory pids -rw-r--r--1root root0May1118:03 /sys/fs/cgroup/kernel_limit/cpu.max
2,问题已经解决
cpu memory pids -rw-r--r--1root root0May1118:03 /sys/fs/cgroup/kernel_limit/cpu.max

说明:

  1. 根 cgroup 的cpucontroller 已经成功启用;
  2. /sys/fs/cgroup/kernel_limit/cpu.max已经生成;
  3. 现在脚本可以正常写入 CPU 限制了。

也就是说,之前报错的根因就是:

cgroup.subtree_control里没有启用cpu,所以子 cgroup 没有cpu.max文件。


现在可以先测试写入

你可以运行:

sudosh-c'echo "20000 100000" > /sys/fs/cgroup/kernel_limit/cpu.max'cat/sys/fs/cgroup/kernel_limit/cpu.max

正常应该显示:

20000100000

这就代表 CPU 20% 限制写入成功。


建议把脚本里的 cgroup 设置部分改成这个

这样以后脚本每次运行时,会自动启用+cpu+memory+pids,避免再次遇到cpu.max不存在的问题。

# 2. 设置 cgroup v2 资源限制echo"=== 设置 cgroup 资源限制 ==="CGROUP_PATH="/sys/fs/cgroup/kernel_limit"# CPU 限制 20%PERIOD_US=100000CPU_PERCENT=20QUOTA_US=$((PERIOD_US*CPU_PERCENT/100))# 内存限制# 注意:这里是 600M,不是 6000M。# 如果你确实要 6000M,把 MEMORY_MAX 改成 "6000M"。MEMORY_MAX="600M"SWAP_MAX="1G"sudosh-c" set -e # 启用父级 cgroup controller echo '+cpu' > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true echo '+memory' > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true echo '+pids' > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true # 如果旧 cgroup 存在,先尝试清理 if [ -d '${CGROUP_PATH}' ]; then for pid in \$(cat'${CGROUP_PATH}/cgroup.procs'2>/dev/null||true); do echo \$pid> /sys/fs/cgroup/cgroup.procs 2>/dev/null || true done rmdir '${CGROUP_PATH}' 2>/dev/null || true fi # 重新创建 cgroup mkdir -p '${CGROUP_PATH}' # 检查 cpu.max 是否存在 if [ ! -e '${CGROUP_PATH}/cpu.max' ]; then echo '错误:${CGROUP_PATH}/cpu.max 不存在,cpu controller 没有成功启用。' echo '当前 /sys/fs/cgroup/cgroup.subtree_control 内容:' cat /sys/fs/cgroup/cgroup.subtree_control exit 1 fi # 写入资源限制 echo '${QUOTA_US}${PERIOD_US}' > '${CGROUP_PATH}/cpu.max' echo '${MEMORY_MAX}' > '${CGROUP_PATH}/memory.max' echo '${SWAP_MAX}' > '${CGROUP_PATH}/memory.swap.max' "echo"资源限制已设置:CPU${CPU_PERCENT}% | RAM ≤${MEMORY_MAX}| Swap ≤${SWAP_MAX}"

你的 cleanup 函数可以继续保留

不过有一点要注意:你的 cleanup 里面如果执行了:

rmdir${CGROUP_PATH}

那么下次脚本启动时,需要重新创建 cgroup。
上面这段新版设置逻辑已经包含:

mkdir-p'${CGROUP_PATH}'

所以没问题。


现在你可以重新运行脚本

./linux_cgroups_v2.sh

如果还想确认限制是否生效,可以另开一个 SSH 窗口执行:

cat/sys/fs/cgroup/kernel_limit/cpu.maxcat/sys/fs/cgroup/kernel_limit/memory.maxcat/sys/fs/cgroup/kernel_limit/memory.swap.maxcat/sys/fs/cgroup/kernel_limit/cgroup.procs

你应该看到类似:

20000100000600M 1G

然后cgroup.procs里会有被限制的进程 PID。


小结

现在状态是正常的:

cgroup.subtree_control=cpu memory pids cpu.max 已存在

所以之前的Permission denied已经可以解释清楚并修复了。
接下来直接跑修改后的脚本即可。

http://www.jsqmd.com/news/804892/

相关文章:

  • 鼻毛剪刀哪个牌子好?鼻毛修剪器哪个牌子好?鼻毛剪十大品牌推荐
  • C#/.NET/.NET Core技术前沿周刊 | 第 70 期(2026年5.01-5.10)
  • 基于 JTT1078MediaServer 的集群方案实践(Nginx + 溯源模式)轻量级车联网音视频集群
  • AzurLaneAutoScript终极指南:如何彻底解放你的碧蓝航线游戏时间
  • RST风暴:从TCP复位包探秘ECONNABORTED的深层网络诱因与防御策略
  • 时间差分学习:结合动态规划和蒙特卡洛方法进行强化学习
  • 必看!移动岗亭厂家交货及时性测评,日硕科技排名第一!
  • 基于NoneBot2与OpenAI API构建智能QQ聊天机器人:从原理到部署实践
  • 图片去水印工具推荐:2026免费去水印方法哪个好用? - 科技热点发布
  • 基于Docker与LLM的个人AI管家MPA:架构解析与实战部署指南
  • OpenClaw-Simplex插件:构建私有AI通信通道的完整指南
  • 厚街婚纱摄影哪家值得推荐:秒杀婚纱摄影质感绝佳 - 13724980961
  • 工程师视角:最低成本脱碳路径与气候解决方案的工程化思维
  • static数组定义在函数外部(静态全局数组),作用域被限制在当前源文件中,这个源文件被include到其他文件,static数组的可见性
  • 望舒AI助手:零依赖部署与自动化配置实战解析
  • 告别手动计算!用Python脚本一键生成Vivado ROM所需的.coe正弦波文件
  • 大模型评测实战指南:从基准测试到业务落地的科学评估体系
  • 2026年AI思维导图工具横向对比:6款工具实测分享
  • ClawCures:基于规划与执行分离的AI药物研发智能体平台实战
  • 免费去图片水印App排行榜2026:一键去水印哪款好用?免费一键去图片水印App推荐 - 科技热点发布
  • 对抗AI“谄媚”的三层防御系统:让AI编程助手具备批判性思维
  • 迈克生物、迈瑞、安图怎么选?医学检验智慧实验室品牌选型维度
  • [算法训练] LeetCode Hot100 学习笔记#22
  • 智能产品系统架构分析 - 智能办公系统架构分层
  • 通过地理空间插值进行温度重建
  • Java实现Gemma大模型推理:轻量级AI集成与生产部署指南
  • 嘉兴代理记账哪家好?高性价比会计事务所盘点 - 速递信息
  • 物流分析怎么做?物流分析真正实用的20个公式,整理好了一键套用!
  • m4s-converter:B站缓存视频无损转换完整指南
  • 五分钟部署专属AI助手:基于Railway与OpenClaw的零运维实践