시놀로지 팬 가드 추가

This commit is contained in:
seo committed 2026-07-31 06:11:36 +09:00
1 parent 33851e0189
commit 17dacd896f
3 files changed
+129

No files matched your search

+4
View File
@@ -102,6 +102,10 @@ Control은 라즈베리파이/리눅스 호스트의 팬과 시스템 상태를
커널 패닉이나 강제 재부팅 분석을 위해 `systemd-journald`는 `/var/log/journal`에 영구 저장합니다. `dtoverlay=ramoops` 기반 pstore는 부팅 직후 `control-pstore-collect.service`가 `/var/log/pstore`로 복사합니다. 현재 pstore에 남은 크래시 조각이 없으면 이 서비스는 조건 불충족으로 `inactive`일 수 있으며 정상입니다.
## 시놀로지 팬 가드
시놀로지 CPU 온도는 `k10temp`의 `Tdie` 값을 기준으로 보고, `nct6795`의 실제 회전 팬 `fan2_input`과 `pwm2`를 감시합니다. `bin/synology_fan_guard.sh`는 DSM 기본 팬 제어를 평소에는 유지하고, CPU가 75도 이상이면 `pwm2`를 255로 강제합니다. CPU가 65도 이하로 내려가고 수동 강제 상태라면 DSM 자동제어(`pwm2_enable=5`)로 되돌립니다. systemd 예시는 `systemd/synology-fan-guard.service`에 둡니다.
## UPS/배터리 상태
UPS가 과부하 상황에서 전압 하강과 강제 종료를 반복해 현재 운영 구성에서는 제거되어 있습니다. 이에 따라 Control은 기본적으로 MAX17048 배터리 센서를 읽지 않고, 배터리 SOC/전압 차트와 잔여 시간 UI도 표시하지 않습니다.
+113
View File
@@ -0,0 +1,113 @@
#!/bin/sh
set -eu
INTERVAL_SECONDS="${INTERVAL_SECONDS:-5}"
HIGH_TEMP_C="${HIGH_TEMP_C:-75}"
LOW_TEMP_C="${LOW_TEMP_C:-65}"
PWM_CHANNEL="${PWM_CHANNEL:-2}"
PWM_FULL="${PWM_FULL:-255}"
PWM_AUTO_ENABLE="${PWM_AUTO_ENABLE:-5}"
PWM_MANUAL_ENABLE="${PWM_MANUAL_ENABLE:-1}"
LAST_MODE=""
log() {
if command -v logger >/dev/null 2>&1; then
logger -t syno-fan-guard "$*"
fi
printf '%s\n' "$*"
}
hwmon_by_name() {
target="$1"
for hwmon in /sys/class/hwmon/hwmon*; do
[ -r "$hwmon/name" ] || continue
[ "$(cat "$hwmon/name" 2>/dev/null)" = "$target" ] || continue
printf '%s\n' "$hwmon"
return 0
done
return 1
}
read_cpu_temp_mc() {
cpu_hwmon="$(hwmon_by_name k10temp || true)"
if [ -n "$cpu_hwmon" ]; then
for sensor in temp2_input temp1_input temp3_input; do
path="$cpu_hwmon/$sensor"
[ -r "$path" ] || continue
value="$(cat "$path" 2>/dev/null || printf 0)"
case "$value" in
''|*[!0-9-]*) continue ;;
esac
[ "$value" -gt 0 ] || continue
printf '%s\n' "$value"
return 0
done
fi
printf '0\n'
}
fan_hwmon() {
hwmon_by_name nct6795
}
write_if_needed() {
path="$1"
value="$2"
[ -w "$path" ] || return 1
current="$(cat "$path" 2>/dev/null || printf '')"
[ "$current" = "$value" ] && return 0
printf '%s\n' "$value" > "$path"
}
apply_once() {
verbose="${1:-0}"
fan_hwmon_path="$(fan_hwmon)"
pwm_path="$fan_hwmon_path/pwm${PWM_CHANNEL}"
enable_path="$fan_hwmon_path/pwm${PWM_CHANNEL}_enable"
rpm_path="$fan_hwmon_path/fan${PWM_CHANNEL}_input"
temp_mc="$(read_cpu_temp_mc)"
temp_c=$((temp_mc / 1000))
rpm=0
[ -r "$rpm_path" ] && rpm="$(cat "$rpm_path" 2>/dev/null || printf 0)"
enable="$(cat "$enable_path" 2>/dev/null || printf '?')"
pwm="$(cat "$pwm_path" 2>/dev/null || printf '?')"
if [ "$temp_c" -ge "$HIGH_TEMP_C" ]; then
write_if_needed "$enable_path" "$PWM_MANUAL_ENABLE"
write_if_needed "$pwm_path" "$PWM_FULL"
if [ "$LAST_MODE" != "force-full" ] || [ "$verbose" = "1" ]; then
log "force-full temp=${temp_c}C rpm=${rpm} pwm=${pwm} enable=${enable}"
fi
LAST_MODE="force-full"
return 0
fi
if [ "$temp_c" -le "$LOW_TEMP_C" ] && [ "$enable" != "$PWM_AUTO_ENABLE" ]; then
write_if_needed "$enable_path" "$PWM_AUTO_ENABLE"
log "restore-auto temp=${temp_c}C rpm=${rpm} pwm=${pwm} enable=${enable}"
LAST_MODE="auto"
return 0
fi
if [ "$verbose" = "1" ]; then
log "observe temp=${temp_c}C rpm=${rpm} pwm=${pwm} enable=${enable}"
fi
LAST_MODE="observe"
}
case "${1:-run}" in
once|status)
apply_once 1
;;
run)
log "start high=${HIGH_TEMP_C}C low=${LOW_TEMP_C}C channel=${PWM_CHANNEL}"
while :; do
apply_once 0 || true
sleep "$INTERVAL_SECONDS"
done
;;
*)
printf 'Usage: %s [run|once|status]\n' "$0" >&2
exit 2
;;
esac
+12
View File
@@ -0,0 +1,12 @@
[Unit]
Description=Synology CPU temperature fan guard
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/local/sbin/synology-fan-guard run
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target