You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于系统负载动态限制后台进程CPU使用率的实现方案咨询

基于系统负载动态限制后台进程CPU使用率的实现方案咨询

嘿,这个需求太贴合实际了——跑编码这类吃满CPU的后台任务,又不想让前台操作卡成幻灯片对吧?我给你分享几个跨shell都能稳定生效的方案,都是我自己折腾过的:

方案一:cpulimit + 自定义负载监控脚本(最灵活)

cpulimit是专门用来限制进程CPU使用率的工具,配合一个简单的shell脚本就能实现动态调整,不管你的ffmpeg是在哪个终端启动的,只要进程还在跑就能生效。

步骤:

  1. 安装cpulimit
    根据你的系统选择命令:

    • Debian/Ubuntu系:sudo apt update && sudo apt install cpulimit
    • RHEL/CentOS系:sudo yum install cpulimit(或者从GitHub源码编译安装)
    • macOS:brew install cpulimit
  2. 编写动态调整脚本
    新建一个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
    
  3. 启动脚本
    给脚本加执行权限:chmod +x dynamic_cpu_control.sh
    然后后台运行:./dynamic_cpu_control.sh &
    (如果怕终端关了脚本停掉,可以用nohup ./dynamic_cpu_control.sh &,输出会存到nohup.out里)

方案二:systemd服务托管(适合长期运行的任务)

如果你的系统用systemd(现在大部分Linux发行版都是),可以把ffmpeg和监控脚本都做成systemd服务,这样就算你关了所有终端,任务也能在后台稳定运行,负载调整逻辑也不会断。

步骤:

  1. 创建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
    
  2. 创建负载监控服务
    新建/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
    
  3. 启动并启用服务

    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没生效,随时告诉我你的系统和具体情况,我再帮你调!

火山引擎 最新活动