飞牛os控制风扇转速的脚本实现降噪

前言

双十一入了拾光坞G2,性价比其实很高,3盘位完全满足我的需求,还是品牌NAS,官方支持刷机且有3年质保,到手直接刷飞牛,近乎完美。
唯一缺点就是默认40%的风扇有点吵,飞牛系统没有风扇控制的选项,装了CoolerControl但没有风扇驱动,BIOS好像也是阉割过的没有风扇控制功能。找了一圈发现fanctrl可以控制,改写了一个控温脚本,目前感觉不错。

手动控制风扇转速

下载G2 风扇控制转速程序

wget  http://down.sgwbox.com/tools/x86/fanctrl /root/fanctrl

chmod +x  /root/fanctrl

用法
<code>./fanctrl (0~100)</code>
例如:
<code>./fanctrl 30</code> 表示设置风扇转速为30%
<code>./fanctrl 80 </code>表示设置风扇转速为80%
实测常规设置风扇转速为35%是基本听不到声音的;大于60就开始吵了。

风控脚本并开机自启

原帖的脚本我测试后无法正常工作,所以用豆包写了一个,感觉不错就分享出来,有问题直接发给AI就可以修改。
脚本功能

  1. 多源温度检测
  2. 智能风扇控制
  3. 完整日志记录
  4. 休眠保护

    风扇温控脚本(<code>fan_control.sh</code>)

#!/bin/bash
set -eo pipefail

# ================================== 配置项 ==================================
STATE_FILE=&quot;/var/run/fan_control.state&quot;    # 状态保存文件
LOG_FILE=&quot;/var/log/fan_control.log&quot;        # 日志文件
FAN_CTRL=&quot;/root/fanctrl&quot;                   # 风扇控制程序路径
CHECK_INTERVAL=60                          # 检测间隔(秒)
MAX_CPU_TEMP=80                            # CPU温度阈值(℃)
MAX_HDD_TEMP=50                            # 硬盘温度阈值(℃)
SAFE_FAN_SPEED=30                          # 安全温度下的风扇转速(%)
INCREASE_STEP=10                           # 超温时每次增加的转速(%)
MAX_FAN_SPEED=100                          # 最大风扇转速(%)
# =============================================================================

# 初始化日志和状态文件
init_files() {
    # 创建日志文件(确保权限)
    if [ ! -f &quot;$LOG_FILE&quot; ]; then
        touch &quot;$LOG_FILE&quot;
        chmod 644 &quot;$LOG_FILE&quot;
    fi
    # 初始化状态文件
    if [ ! -f &quot;$STATE_FILE&quot; ]; then
        echo &quot;current_speed=$SAFE_FAN_SPEED&quot; &gt; &quot;$STATE_FILE&quot;
        echo &quot;last_action=initialized&quot; &gt;&gt; &quot;$STATE_FILE&quot;
        echo &quot;last_temp_check=$(date +%s)&quot; &gt;&gt; &quot;$STATE_FILE&quot;
        # 初始设置风扇转速
        if [ -x &quot;$FAN_CTRL&quot; ]; then
            &quot;$FAN_CTRL&quot; &quot;$SAFE_FAN_SPEED&quot; &gt;/dev/null 2&gt;&amp;1
            log &quot;初始化风扇转速为 $SAFE_FAN_SPEED%&quot;
        else
            log &quot;错误:未找到风扇控制程序 $FAN_CTRL,请先安装&quot;
            exit 1
        fi
    fi
}

# 日志记录函数
log() {
    local timestamp=$(date +&quot;%Y-%m-%d %H:%M:%S&quot;)
    echo &quot;[$timestamp] $1&quot; &gt;&gt; &quot;$LOG_FILE&quot;
}

# 读取当前状态
read_state() {
    source &quot;$STATE_FILE&quot; 2&gt;/dev/null || {
        log &quot;状态文件损坏,重新初始化&quot;
        init_files
        source &quot;$STATE_FILE&quot;
    }
}

# 更新状态文件
update_state() {
    local speed=$1
    local action=$2
    echo &quot;current_speed=$speed&quot; &gt; &quot;$STATE_FILE&quot;
    echo &quot;last_action=$action&quot; &gt;&gt; &quot;$STATE_FILE&quot;
    echo &quot;last_temp_check=$(date +%s)&quot; &gt;&gt; &quot;$STATE_FILE&quot;
}

# 获取CPU温度(兼容多种系统)
get_cpu_temp() {
    # 优先尝试x86_pkg_temp
    if [ -f &quot;/sys/class/thermal/thermal_zone0/temp&quot; ]; then
        local temp=$(cat /sys/class/thermal/thermal_zone0/temp 2&gt;/dev/null)
        if [ -n &quot;$temp&quot; ] &amp;&amp; [ &quot;$temp&quot; -gt 0 ]; then
            echo $((temp / 1000))
            return 0
        fi
    fi
    # 尝试coretemp(多核心取最高)
    local core_temp=$(sensors | grep -i &#039;core&#039; | grep -oP &#039;\d+°C&#039; | grep -oP &#039;\d+&#039; | sort -nr | head -1)
    if [ -n &quot;$core_temp&quot; ]; then
        echo &quot;$core_temp&quot;
        return 0
    fi
    # 尝试proc文件系统
    local proc_temp=$(cat /proc/cpuinfo | grep -i &#039;temperature&#039; | grep -oP &#039;\d+&#039; | head -1)
    if [ -n &quot;$proc_temp&quot; ]; then
        echo &quot;$proc_temp&quot;
        return 0
    fi
    # 所有方法失败
    log &quot;警告:无法获取CPU温度&quot;
    return 1
}

# 获取硬盘温度(兼容多种检测方式)
get_hdd_temp() {
    local hdd_devices=$(lsblk -o NAME,TYPE | grep -i &#039;disk&#039; | grep -v &#039;loop&#039; | awk &#039;{print $1}&#039;)
    local max_hdd_temp=0

    for dev in $hdd_devices; do
        local device=&quot;/dev/$dev&quot;
        # 检查硬盘是否休眠,避免唤醒
        if hdparm -C &quot;$device&quot; 2&gt;/dev/null | grep -qi &#039;standby\|sleeping&#039;; then
            continue
        fi
        # 尝试smartctl
        local temp=$(smartctl -A &quot;$device&quot; 2&gt;/dev/null | grep -i &#039;temperature&#039; | awk &#039;{print $10}&#039; | head -1)
        if [ -z &quot;$temp&quot; ] || [ &quot;$temp&quot; -eq 0 ]; then
            # 尝试hddtemp
            temp=$(hddtemp -n &quot;$device&quot; 2&gt;/dev/null)
        fi
        # 记录最高温度
        if [ -n &quot;$temp&quot; ] &amp;&amp; [ &quot;$temp&quot; -gt &quot;$max_hdd_temp&quot; ]; then
            max_hdd_temp=$temp
        fi
    done

    if [ &quot;$max_hdd_temp&quot; -gt 0 ]; then
        echo &quot;$max_hdd_temp&quot;
        return 0
    else
        log &quot;警告:无法获取硬盘温度&quot;
        return 1
    fi
}

# 控制风扇转速
control_fan() {
    local target_speed=$1
    # 检查转速范围
    if [ &quot;$target_speed&quot; -lt 0 ] || [ &quot;$target_speed&quot; -gt 100 ]; then
        log &quot;无效转速 $target_speed%,限制在0-100之间&quot;
        target_speed=$(( target_speed &lt; 0 ? 0 : 100 ))
    fi
    # 执行转速设置
    if [ -x &quot;$FAN_CTRL&quot; ]; then
        &quot;$FAN_CTRL&quot; &quot;$target_speed&quot; &gt;/dev/null 2&gt;&amp;1
        if [ $? -eq 0 ]; then
            log &quot;风扇转速已设置为 $target_speed%&quot;
            return 0
        else
            log &quot;错误:设置风扇转速 $target_speed% 失败&quot;
            return 1
        fi
    else
        log &quot;错误:风扇控制程序 $FAN_CTRL 不存在或不可执行&quot;
        return 1
    fi
}

# 温度监控主逻辑
monitor_temps() {
    read_state
    local current_speed=$current_speed

    # 获取温度
    local cpu_temp=$(get_cpu_temp)
    local hdd_temp=$(get_hdd_temp)

    # 检查温度是否有效
    local temp_valid=1
    if [ -z &quot;$cpu_temp&quot; ] &amp;&amp; [ -z &quot;$hdd_temp&quot; ]; then
        log &quot;无法获取任何温度数据,跳过本次调整&quot;
        temp_valid=0
    fi

    if [ $temp_valid -eq 1 ]; then
        # 决定是否需要调整转速
        local need_increase=0
        if [ -n &quot;$cpu_temp&quot; ] &amp;&amp; [ &quot;$cpu_temp&quot; -ge &quot;$MAX_CPU_TEMP&quot; ]; then
            need_increase=1
        fi
        if [ -n &quot;$hdd_temp&quot; ] &amp;&amp; [ &quot;$hdd_temp&quot; -ge &quot;$MAX_HDD_TEMP&quot; ]; then
            need_increase=1
        fi

        # 计算目标转速
        local target_speed=$current_speed
        if [ $need_increase -eq 1 ]; then
            # 超温时逐步增加转速
            target_speed=$((current_speed + INCREASE_STEP))
            if [ &quot;$target_speed&quot; -gt &quot;$MAX_FAN_SPEED&quot; ]; then
                target_speed=$MAX_FAN_SPEED
            fi
        else
            # 温度正常时恢复到安全转速
            if [ &quot;$current_speed&quot; -ne &quot;$SAFE_FAN_SPEED&quot; ]; then
                target_speed=$SAFE_FAN_SPEED
            fi
        fi

        # 执行调整(只有转速变化时才操作)
        if [ &quot;$target_speed&quot; -ne &quot;$current_speed&quot; ]; then
            if control_fan &quot;$target_speed&quot;; then
                update_state &quot;$target_speed&quot; &quot;温度触发调整 (CPU: ${cpu_temp:-未知}°C, HDD: ${hdd_temp:-未知}°C)&quot;
            fi
        else
            log &quot;CPU温度: ${cpu_temp:-未知}°C, 硬盘温度: ${hdd_temp:-未知}°C, 风扇转速: $current_speed% (无需调整)&quot;
        fi
    fi
}

# 显示状态
show_status() {
    read_state
    local cpu_temp=$(get_cpu_temp || echo &quot;未知&quot;)
    local hdd_temp=$(get_hdd_temp || echo &quot;未知&quot;)

    echo &quot;===== 风扇温控状态 =====&quot;
    echo &quot;当前风扇转速: $current_speed%&quot;
    echo &quot;CPU温度阈值: $MAX_CPU_TEMP°C&quot;
    echo &quot;硬盘温度阈值: $MAX_HDD_TEMP°C&quot;
    echo &quot;&quot;
    echo &quot;CPU当前温度: $cpu_temp°C&quot;
    echo &quot;硬盘当前温度: $hdd_temp°C&quot;
    echo &quot;&quot;
    echo &quot;最后操作: $last_action&quot;
    echo &quot;========================&quot;
}

# 主程序入口
main() {
    # 检查是否以root运行
    if [ &quot;$(id -u)&quot; -ne 0 ]; then
        echo &quot;错误:请以root权限运行(sudo)&quot;
        exit 1
    fi

    # 检查依赖
    local dependencies=(&quot;hdparm&quot; &quot;hddtemp&quot; &quot;sensors&quot;)
    for dep in &quot;${dependencies[@]}&quot;; do
        if ! command -v &quot;$dep&quot; &amp;&gt;/dev/null; then
            echo &quot;错误:缺少依赖 $dep,请先安装&quot;
            exit 1
        fi
    done

    init_files

    case &quot;$1&quot; in
        --service)
            log &quot;启动风扇温控服务(间隔 $CHECK_INTERVAL 秒)&quot;
            while true; do
                monitor_temps
                sleep $CHECK_INTERVAL
            done
            ;;
        --status)
            show_status
            ;;
        --log)
            tail -f &quot;$LOG_FILE&quot;
            ;;
        --restart)
            log &quot;手动重启服务&quot;
            control_fan &quot;$SAFE_FAN_SPEED&quot;
            update_state &quot;$SAFE_FAN_SPEED&quot; &quot;手动重启&quot;
            echo &quot;服务已重启,风扇转速重置为 $SAFE_FAN_SPEED%&quot;
            ;;
        *)
            echo &quot;用法:&quot;
            echo &quot;  $0 --service   启动温控服务(守护进程)&quot;
            echo &quot;  $0 --status    查看当前状态&quot;
            echo &quot;  $0 --log       查看实时日志&quot;
            echo &quot;  $0 --restart   重启服务并重置风扇转速&quot;
            exit 1
            ;;
    esac
}

main &quot;$@&quot;

脚本改进说明

  1. 增强兼容性:优化了 CPU / 硬盘温度检测逻辑,适配更多 Linux 发行版(。
  2. 完善错误处理:增加了文件权限检查、依赖检测、程序存在性验证,避免静默失败。
  3. 状态可视化:<code>--status</code> 命令更清晰地展示当前状态,方便排查问题。
  4. 可靠性提升:增加了 <code>--restart</code> 命令,可手动重置状态,解决可能的状态文件损坏问题。
  5. 日志优化:更详细的日志记录,便于追踪脚本运行情况。

使用步骤

  1. 安装基础依赖(确保先执行):

    apt update && apt install -y hdparm hddtemp smartmontools lm-sensors
    sensors-detect  # 按提示完成传感器检测(一路按回车即可)
  2. 下载风扇控制程序

    wget http://down.sgwbox.com/tools/x86/fanctrl -O /root/fanctrl && chmod +x /root/fanctrl
  3. 创建新脚本

    # 复制上面的脚本内容到文件中
    nano /usr/local/bin/fan_control.sh
    # 保存后设置权限
    chmod +x /usr/local/bin/fan_control.sh
  4. 测试脚本

    # 查看状态(验证是否正常运行)
    /usr/local/bin/fan_control.sh --status
  5. 设置系统服务(开机自启):

    # 创建服务文件
    tee /etc/systemd/system/fan-control.service <<EOF
    [Unit]
    Description=Fan Control Service
    After=multi-user.target
    
    [Service]
    Type=simple
    ExecStart=/usr/local/bin/fan_control.sh --service
    Restart=always
    RestartSec=60
    User=root
    WorkingDirectory=/root
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    # 启动并设置自启
    systemctl daemon-reload
    systemctl enable --now fan-control
    
  6. 检查服务状态

    systemctl status fan-control  # 查看服务是否运行
    tail -f /var/log/fan_control.log  # 查看实时日志


如果运行仍有问题,可通过日志文件 <code>/var/log/fan_control.log</code> 查看具体错误信息,或执行 <code>systemctl status fan-control</code> 检查服务状态,以便进一步排查。

安装依赖

  • 安装 <code>hddtemp</code> 依赖,按以下步骤安装即可解决,部分系统需额外处理兼容性问题。

    第一步:优先常规安装

  1. 执行标准安装命令(适用于 Debian/Ubuntu/PVE 等基于 Debian 的系统):

    apt update && apt install -y hddtemp
  2. 安装完成后,重新运行脚本测试:

    /usr/local/bin/fan_control.sh --status

    第二步:若安装失败(无软件包)

  3. 先确认软件源是否包含 <code>hddtemp</code>,执行搜索:

    apt search hddtemp
  4. 若搜索结果为空,手动下载安装(以 Debian 12/ Ubuntu 22.04 为例):

    # 下载适配 x86_64 架构的 deb 包
    wget http://ftp.debian.org/debian/pool/main/h/hddtemp/hddtemp_0.3-beta15-54_amd64.deb
    # 安装下载的包
    dpkg -i hddtemp_0.3-beta15-54_amd64.deb
    # 修复依赖缺失(若有报错)
    apt -f install -y

    第三步:安装后验证

    command -v hddtemp  # 输出 /usr/sbin/hddtemp 即成功
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇