基于系统负载动态限制后台进程CPU使用率的实现方案咨询
基于系统负载动态限制后台进程CPU使用率的实现方案咨询
嘿,这个需求太贴合实际了——跑编码这类吃满CPU的后台任务,又不想让前台操作卡成幻灯片对吧?我给你分享几个跨shell都能稳定生效的方案,都是我自己折腾过的:
方案一:cpulimit + 自定义负载监控脚本(最灵活)
cpulimit是专门用来限制进程CPU使用率的工具,配合一个简单的shell脚本就能实现动态调整,不管你的ffmpeg是在哪个终端启动的,只要进程还在跑就能生效。
步骤:
安装cpulimit
根据你的系统选择命令:- Debian/Ubuntu系:
sudo apt update && sudo apt install cpulimit - RHEL/CentOS系:
sudo yum install cpulimit(或者从GitHub源码编译安装) - macOS:
brew install cpulimit
- Debian/Ubuntu系:
编写动态调整脚本
新建一个dynamic_cpu_control.sh文件,内容如下:#!/bin/bash # 配置参数,根据你的情况修改 TARGET="ffmpeg" # 可以替换成进程PID,或者用进程名 CPU_CORES=$(nproc) # 获取当前系统的CPU核心数 # 负载阈值:比如当1分钟负载超过核心数的80%时,触发降频 LOAD_THRESHOLD=$(echo "$CPU_CORES * 0.8" | bc) CHECK_INTERVAL=5 # 每5秒检查一次负载,可按需调整 while true; do # 检查目标进程是否存在 if ! pgrep -x "$TARGET" > /dev/null; then echo "目标进程$TARGET已退出,脚本将在30秒后再次检查..." sleep 30 continue fi # 获取当前1分钟系统负载(处理不同系统的格式差异) CURRENT_LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr ',' '.') # 比较负载和阈值 if (( $(echo "$CURRENT_LOAD > $LOAD_THRESHOLD" | bc -l) )); then # 负载过高,限制到10% CPU echo "[$(date)] 系统负载过高(当前$CURRENT_LOAD > 阈值$LOAD_THRESHOLD),将$TARGET的CPU限制调整为10%" cpulimit -e "$TARGET" -l 10 -b else # 负载正常,解除限制(设为100%) echo "[$(date)] 系统负载正常,将$TARGET的CPU限制调整为100%" cpulimit -e "$TARGET" -l 100 -b fi sleep $CHECK_INTERVAL done启动脚本
给脚本加执行权限:chmod +x dynamic_cpu_control.sh
然后后台运行:./dynamic_cpu_control.sh &
(如果怕终端关了脚本停掉,可以用nohup ./dynamic_cpu_control.sh &,输出会存到nohup.out里)
方案二:systemd服务托管(适合长期运行的任务)
如果你的系统用systemd(现在大部分Linux发行版都是),可以把ffmpeg和监控脚本都做成systemd服务,这样就算你关了所有终端,任务也能在后台稳定运行,负载调整逻辑也不会断。
步骤:
创建ffmpeg编码服务
新建/etc/systemd/system/ffmpeg-encode.service:[Unit] Description=FFmpeg视频编码后台任务 After=network.target # 如果需要网络的话加,不需要可以删掉 [Service] User=your_username # 替换成你的用户名 ExecStart=/usr/bin/ffmpeg -i /path/to/input.mp4 -c:v libx265 /path/to/output.mkv # 初始设置最低优先级,让系统优先处理前台任务 Nice=19 IoniceClass=3 Type=simple Restart=no # 任务完成后自动退出,不需要重启 [Install] WantedBy=multi-user.target创建负载监控服务
新建/etc/systemd/system/cpu-limit-monitor.service:[Unit] Description=动态调整ffmpeg CPU使用率的监控服务 After=ffmpeg-encode.service [Service] User=your_username ExecStart=/path/to/your/dynamic_cpu_control.sh # 替换成你脚本的绝对路径 Restart=on-failure # 脚本意外退出时自动重启 Type=simple [Install] WantedBy=multi-user.target启动并启用服务
sudo systemctl daemon-reload sudo systemctl start ffmpeg-encode.service sudo systemctl start cpu-limit-monitor.service如果需要开机自启,可以加
enable:sudo systemctl enable ffmpeg-encode.service sudo systemctl enable cpu-limit-monitor.service
额外注意事项
- 进程匹配的小技巧:如果你的系统里有多个ffmpeg进程,用进程名会同时限制所有,这时候可以用PID。启动ffmpeg的时候把PID存到文件:
ffmpeg -i input.mp4 output.mkv & echo $! > /var/run/ffmpeg.pid,然后脚本里把TARGET换成$(cat /var/run/ffmpeg.pid),再把cpulimit -e $TARGET改成cpulimit -p $TARGET。 - 负载阈值调整:
LOAD_THRESHOLD可以根据你的需求改,比如如果CPU是4核,设成3.2(4*0.8),意思是当1分钟负载超过3.2时就降频。 - macOS的小差异:macOS的
uptime负载格式和Linux一样,但nproc需要换成sysctl -n hw.ncpu,脚本里的CPU_CORES=$(sysctl -n hw.ncpu)就行。
要是你在测试过程中遇到问题,比如脚本读取负载不对,或者cpulimit没生效,随时告诉我你的系统和具体情况,我再帮你调!




