- 新增
get_cpu_temp() 函数:从 /sys/class/thermal/thermal_zone*/temp 读取 CPU 温度
- 主逻辑取
max(硬盘最高温, CPU温度)
- 兼容无
lm-sensors 的精简系统(不依赖 sensors 命令)
- 保留原有 SATA/NVMe 支持
- ✅ 修复 SATA 硬盘温度读取(适配你的
194 Temperature_Celsius 输出)
- ✅ 支持 NVMe 和 SATA 混合环境
- ✅ 不依赖
jq 或 lsblk,兼容飞牛精简系统
- ✅ 自动识别
/dev/sdX 和 /dev/nvmeXn1
- ✅ 温控曲线可自定义
- ✅ 日志记录 + 开机自启友好
完整脚本:/root/fan_auto.sh(含 CPU + 硬盘双温控)
#!/bin/bash
# 拾光坞 G2 风扇自动调速脚本(CPU + 硬盘双温控版)
# 支持 SATA / NVMe / CPU 温度 | 无需 jq / sensors | 适配飞牛 fnOS
# 作者:Qwen | 2025-12-18
FANCTRL="/root/fanctrl"
LOGFILE="/var/log/fan_auto.log"
INTERVAL=30
# 温度 → 风扇转速映射(百分比)
declare -A SPEED_MAP=(
[0]=30 # <=40°C
[41]=35
[45]=40
[50]=50
[55]=60
[60]=70
[65]=80
[70]=90
[75]=100
)
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOGFILE"
}
# 获取所有硬盘设备
get_disks() {
for dev in /dev/sd[a-z]; do [[ -e "$dev" ]] && echo "$dev"; done
for dev in /dev/nvme[0-9]n[0-9]; do [[ -e "$dev" ]] && echo "$dev"; done
}
# 获取硬盘温度
get_disk_temp() {
local dev="$1"
if [[ -z "$dev" ]] || [[ ! -e "$dev" ]]; then
echo 0
return
fi
local temp=""
temp=$(smartctl -A "$dev" 2>/dev/null | awk '$1 == "194" {print $10; exit}')
if [[ -z "$temp" ]] || ! [[ "$temp" =~ ^[0-9]+$ ]]; then
temp=$(smartctl -A "$dev" 2>/dev/null | awk '/^Temperature:/ && /Celsius/ {print $2; exit}')
fi
if [[ "$temp" =~ ^[0-9]+$ ]] && [[ $temp -ge 0 ]] && [[ $temp -le 80 ]]; then
echo "$temp"
else
echo 0
fi
}
# 获取 CPU 温度(单位:°C)
get_cpu_temp() {
local max_temp=0
local temp_file
# 方法1:通过 /sys/class/thermal/(推荐,无需额外工具)
for zone in /sys/class/thermal/thermal_zone*/; do
if [[ -f "${zone}type" ]] && [[ -f "${zone}temp" ]]; then
type=$(cat "${zone}type" 2>/dev/null)
temp_val=$(cat "${zone}temp" 2>/dev/null)
# 转换为 °C(值通常是 1000 倍)
temp_c=$((temp_val / 1000))
# 只采集 CPU 相关的 zone(如 x86_pkg_temp, coretemp, cpu-*)
if [[ "$type" == *"cpu"* || "$type" == *"core"* || "$type" == *"x86"* ]]; then
if [[ $temp_c -gt $max_temp ]]; then
max_temp=$temp_c
fi
fi
fi
done
# 如果没读到,尝试备用方法(某些系统用 hwmon)
if [[ $max_temp -eq 0 ]]; then
for hwmon in /sys/class/hwmon/hwmon*/; do
if [[ -f "${hwmon}name" ]]; then
name=$(cat "${hwmon}name" 2>/dev/null)
if [[ "$name" == "coretemp" || "$name" == "k10temp" || "$name" == "zenpower" ]]; then
for temp_input in "${hwmon}"temp*_input; do
if [[ -f "$temp_input" ]]; then
temp_c=$(( $(cat "$temp_input") / 1000 ))
if [[ $temp_c -gt $max_temp ]]; then
max_temp=$temp_c
fi
fi
done
fi
fi
done
fi
# 限制合理范围
if [[ $max_temp -ge 0 ]] && [[ $max_temp -le 100 ]]; then
echo $max_temp
else
echo 0
fi
}
# 根据温度获取风扇转速
get_speed_by_temp() {
local temp=$1
local speed=30
for t in 75 70 65 60 55 50 45 41 0; do
if [[ $temp -ge $t ]]; then
speed=${SPEED_MAP[$t]}
break
fi
done
echo $speed
}
# 主程序
main() {
log "=== 风扇自动调速脚本启动(CPU + 硬盘双温控)==="
log "检测间隔: ${INTERVAL} 秒"
while true; do
# 1. 获取硬盘最高温度
disk_max=0
disks=($(get_disks))
for disk in "${disks[@]}"; do
temp=$(get_disk_temp "$disk")
[[ $temp -gt $disk_max ]] && disk_max=$temp
log "DEBUG: Disk $disk = ${temp}°C"
done
# 2. 获取 CPU 温度
cpu_temp=$(get_cpu_temp)
log "DEBUG: CPU = ${cpu_temp}°C"
# 3. 取两者最大值
max_temp=$(( disk_max > cpu_temp ? disk_max : cpu_temp ))
# 4. 控制风扇
target_speed=$(get_speed_by_temp $max_temp)
current_speed=$(cat /tmp/fan_current_speed 2>/dev/null || echo "-1")
if [[ "$current_speed" != "$target_speed" ]]; then
if [[ -x "$FANCTRL" ]]; then
"$FANCTRL" "$target_speed" >/dev/null 2>&1
echo "$target_speed" > /tmp/fan_current_speed
log "🌡️ 最高温度: ${max_temp}°C (CPU:${cpu_temp}°C, Disk:${disk_max}°C) → 🌀 风扇: ${target_speed}%"
else
log "❌ fanctrl 工具缺失!"
exit 1
fi
else
log "📊 当前最高: ${max_temp}°C → 风扇保持 ${target_speed}%"
fi
sleep $INTERVAL
done
}
main
使用步骤(一次性设置)
# 1. 保存脚本
nano /root/fan_auto.sh
# ← 粘贴上面全部内容,Ctrl+O 回车保存,Ctrl+X 退出
# 2. 赋予执行权限
chmod +x /root/fan_auto.sh
# 3. 确保已安装 smartmontools
apt update && apt install -y smartmontools
# 4. 确保 fanctrl 已部署
wget -O /root/fanctrl http://down.sgwbox.com/tools/x86/fanctrl
chmod +x /root/fanctrl
# 5. 测试运行(观察日志)
nohup /root/fan_auto.sh > /dev/null 2>&1 &
tail -f /var/log/fan_auto.log
🔄 设置开机自启(持久化)
# 挂载根分区为可写(飞牛默认只读)
mount -o remount,rw /
# 添加到 rc.local
cat >> /etc/rc.local << 'EOF'
# 启动风扇自动控制
if [ -x /root/fan_auto.sh ]; then
nohup /root/fan_auto.sh > /dev/null 2>&1 &
fi
EOF
# 确保 rc.local 可执行
chmod +x /etc/rc.local
最终效果:
