Debian环境下如何按用户组限制CPU使用?支持组切换场景
解决Debian下用户切换组时自动应用对应CPU限制的方案
嘿,我看你已经搞定了批量添加用户的Bash脚本,现在要实现「用户默认继承主组CPU限制,切换到附属组时自动加载对应组限制」的需求对吧?结合Debian的系统特性,用cgroups(推荐v2版本,Debian 11+默认支持)来实现是最稳定的方案,下面给你一步步拆解:
1. 先给各组建CPU配置文件
咱们先整个专门的目录存各组的CPU限制规则,比如/etc/group-cpu-limits/,每个组对应一个.conf文件。比如主组dev限制2核,就建dev.conf:
CPU_QUOTA=200000 # 这里1核对应100000,2核就是2*100000
附属组qa限制4核,就建qa.conf:
CPU_QUOTA=400000
2. 写个自动应用CPU限制的脚本
创建/usr/local/bin/apply-group-cpu-limit.sh脚本,功能是检测当前用户的有效组,加载对应配置,然后用cgroups设置CPU限制:
#!/bin/bash # 获取当前用户的有效组名和ID CURRENT_GROUP=$(id -gn) CURRENT_GID=$(id -g) # 找对应组的配置文件 CONFIG_FILE="/etc/group-cpu-limits/${CURRENT_GROUP}.conf" if [ -f "$CONFIG_FILE" ]; then # 加载配置里的CPU配额 source "$CONFIG_FILE" # 给当前组创建cgroups目录(不存在就建) CGROUP_DIR="/sys/fs/cgroup/cpu/group-limits/${CURRENT_GROUP}" mkdir -p "$CGROUP_DIR" # 设置cgroups v2的CPU限制(格式是 配额 周期,周期固定1000000) echo "$CPU_QUOTA 1000000" > "$CGROUP_DIR/cpu.max" # 把当前shell进程移到这个cgroup里,生效限制 echo $$ > "$CGROUP_DIR/cgroup.procs" echo "✅ Applied CPU limit: $((CPU_QUOTA/100000)) cores for group $CURRENT_GROUP" else echo "⚠️ No CPU limit config found for group $CURRENT_GROUP" fi
写完别忘了给脚本加执行权限:
chmod +x /usr/local/bin/apply-group-cpu-limit.sh
3. 让用户切换组时自动触发脚本
当用户用newgrp或者sg切换组时,会启动一个新的shell,咱们可以把脚本加到全局shell配置里,让每次启动shell都自动检查应用限制。编辑/etc/bash.bashrc(全局生效,所有用户都适用),末尾加:
# 每次启动shell时自动应用当前组的CPU限制 if [ -x /usr/local/bin/apply-group-cpu-limit.sh ]; then /usr/local/bin/apply-group-cpu-limit.sh fi
这样不管是用户登录,还是切换组启动新shell,都会自动加载当前组的CPU限制了。
4. 把配置逻辑整合到你的批量添加用户脚本里
在你现有的批量脚本里,除了创建用户和组,还要顺便生成对应的CPU配置文件。假设你的用户数据文件每行格式是用户名:主组:主组CPU核数:附属组1:附属组1CPU核数:附属组2:附属组2CPU核数...,可以加这段逻辑:
# 先创建存放组CPU配置的目录 mkdir -p /etc/group-cpu-limits # 读取用户数据文件 while IFS=: read -r username primary_group primary_cpu rest; do # 创建主组(如果不存在) if ! getent group "$primary_group" > /dev/null; then groupadd "$primary_group" fi # 创建用户并指定主组 useradd -g "$primary_group" -m "$username" # 生成主组的CPU配置文件 echo "CPU_QUOTA=$((primary_cpu * 100000))" > "/etc/group-cpu-limits/${primary_group}.conf" # 处理附属组和对应的CPU限制 # 把rest字段按逗号拆分,逐个处理 IFS=, read -ra secondary_groups <<< "$rest" for g in "${secondary_groups[@]}"; do IFS=: read -r sec_group sec_cpu <<< "$g" # 创建附属组(如果不存在) if ! getent group "$sec_group" > /dev/null; then groupadd "$sec_group" fi # 把用户加到附属组 usermod -aG "$sec_group" "$username" # 生成附属组的CPU配置文件 echo "CPU_QUOTA=$((sec_cpu * 100000))" > "/etc/group-cpu-limits/${sec_group}.conf" done done < 你的用户数据文件名.txt
验证一下效果
比如你创建用户John,主组dev(2核),附属组qa(4核):
- 登录John的账号,执行
cat /sys/fs/cgroup/cpu/group-limits/dev/cpu.max,应该看到200000 1000000,说明主组限制生效了 - 执行
newgrp qa切换到qa组,会看到脚本输出✅的提示,再执行cat /sys/fs/cgroup/cpu/group-limits/qa/cpu.max,应该显示400000 1000000,说明切换组后限制自动更新了
一些注意事项
- 确保你的Debian用的是cgroups v2:执行
mount | grep cgroup2,如果没输出,需要编辑/etc/default/grub,在GRUB_CMDLINE_LINUX里加systemd.unified_cgroup_hierarchy=1,然后执行update-grub重启系统 - 设置cgroups目录需要root权限,所以可以给脚本加suid权限:
chmod u+s /usr/local/bin/apply-group-cpu-limit.sh,这样普通用户也能执行 - 如果你用的是老版本Debian(比如10及以下),默认是cgroups v1,那脚本里的cgroup路径和配置项要改,比如用
/sys/fs/cgroup/cpu,cpuacct/group-limits/${CURRENT_GROUP},配置文件用cpu.cfs_quota_us和cpu.cfs_period_us
内容的提问来源于stack exchange,提问作者Aleix Mariné
相关产品推荐
相关产品推荐

