我尝试过以下步骤:
- Cgroups 错误:cgroup 组更改失败
- 如何在 ubuntu 13.04 中使用 cgroup
- https://unix.stackexchange.com/questions/197718/does-managing-cgroups-require-root-access
但它们在 Ubuntu 22.04 上不起作用,大概是因为 cgroups v2 更新所致:
sudo cgcreate -a $USER:$USER -g memory:myGroup -t $USER:$USER
sudo cgset -r memory.max=500M myGroup
sudo cgset -r memory.swap.max=0 myGroup
cgexec -g memory:myGroup id
失败:
cgroup change of group failed
如果我运行它就会起作用sudo
sudo cgexec -g memory:myGroup id
但是然后命令以 的身份运行root
,而我希望它以当前用户的身份运行。
答案1
我读过Linux 内核文档并找到以下内容(重点是我的):
cgroup.procs
所有 cgroup 上都存在的读写换行分隔值文件。...
可以
写入 PID,以将与 PID 关联的进程迁移到 cgroup。写入者应满足以下所有条件。
- 它必须对“cgroup.procs”文件具有写权限。
- 它必须对源和目标 cgroups 的共同祖先的“cgroup.procs”文件具有写访问权限。
...
在这个场景中,共同祖先是/
。所以我让cgroup.procs
根组可写:
sudo chmod o+w /sys/fs/cgroup/cgroup.procs
现在我可以cgexec
以任何非 root 用户身份使用。但不知道是否存在任何安全隐患。
答案2
要解决此问题,您需要通过修改内核的启动参数将主机系统启动到 CGroupV1 模式,其中包括:
systemd.unified_cgroup_hierarchy=false
sudo nano /etc/default/grub
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1 systemd.unified_cgroup_hierarchy=false"
sudo update-grub
sudo reboot
答案3
我曾经在 cgroups v1 中运行过一些资源密集型工具cgexec
。我不太确定 cgroups v2 是否支持此功能;至少我无法让它工作。
在花费大量时间研究之后,我终于找到了在 Ubuntu 22.04 + cgroups v2 中顺利运行的方法。
1. 创建一个 cgroupeurope
并(就我而言)调整权限
$ cd /sys/fs/cgroup/
$ sudo mkdir europe create
$ ls -ld europe
drwxr-x--- 2 root root 0 out 28 22:50 europe
$ sudo chmod a+rx europe
$ ls -ld europe
drwxr-xr-x 2 root root 0 out 28 22:50 europe
如果不改变权限,我会遇到两件事:没有 sudo 就无法在组内 cat 东西,然后systemd-cgtop --depth 1
返回Failed to refresh: Permission denied
。
2. 将 CPU 限制为 3 核,将 RAM 限制为 16G
我有多个可用的控制器(cgroup.controllers
),但只有沿子树传递的控制器是memory
,pids
所以我添加了缺失的cpu
控制器。
$ cat cgroup.controllers // all available
cpuset cpu io memory hugetlb pids rdma misc
$ cat cgroup.subtree_control // for subgroups
memory pids
$ sudo bash -c 'echo '+cpu' > cgroup.subtree_control'
$ cat cgroup.subtree_control // now includes CPU
cpu memory pids
$ cat europe/cgroup.controllers // can confirm in subgrp
cpu memory pids
现在限制 CPU 和 RAM:
$ cat europe/memory.max
max
$ cat europe/cpu.max
max 100000
$ echo '16G' | sudo tee europe/memory.max
16G
$ echo '300000 100000' | sudo tee europe/cpu.max
300000 100000
$ cat europe/memory.max
17179869184
$ cat europe/cpu.max
300000 100000
3. 运行一些东西
我们可以将 PID 添加到europe/cgroup.procs
然后在组中执行europe
。
我不是启动进程然后添加其 PID,而是添加终端窗口的 PID。然后,该 shell 中运行的所有内容都将在组中执行。
打开另一个终端:
$ cat /sys/fs/cgroup/europe/cgroup.procs
$ echo $$ | sudo tee /sys/fs/cgroup/europe/cgroup.procs
25982
$ cat europe/cgroup.procs
25982
26104
$ cat europe/cgroup.procs
25982
26105
$ cat europe/cgroup.procs
25982
26106
第一个 PID 是指代终端(echo $$
在 bash 中匹配),第二个 PID 是命令,cat
这就是为什么每次我运行命令时第二个 PID 都不同。
4. 不需要时删除群组
$ cat /sys/fs/cgroup/europe/cgroup.procs
$ sudo rmdir /sys/fs/cgroup/europe
如果仍有进程,europe/cgroup.procs
我们会收到错误。在此示例中,关闭上一步中添加到组中的终端。
答案4
您可以像这样cgexec
组合:su
sudo cgexec -g memory:myGroup -- su -c 'exec id' $USER
或者简单地使用-s
:
sudo cgexec -g memory:myGroup -- su -s /usr/bin/id $USER
但后者会将$SHELL
变量改写为程序本身。