前言:
DIY的NAS对比成品NAS有性价比高,个人定制化较好等优势,包括我在内的追求性价比的(穷鬼)会被吸引。但是成品NAS也会有很多的优势,例如风扇会随着温度调整,在散热性能噪音之间得到一个比较好的平衡。笔者之前用过QNAP的TS551,硬盘不转的时候是一个安静;目前自己DIY的NAS呢,用的unraid,没法做到自动温度调整(好像有一部分的unraid可以用插件实现,但是我的主板不行,提示占不到转速控制器),那就只能DIY了。
对于NAS来说,最终要的就是硬盘的温度,那么第一步,就是在unraid里面,怎么知道目前的硬盘状态。
一些网上找到的实现方式:
其实UNRAID里面已经装了smartctl,我估计系统默认的获取硬盘的方式就是调用他而来的。python下有pysmart包,实际上它也调用了smartctl,但是我发现这个包有个问题,一旦查询硬盘温度的时候,他会唤醒全部的硬盘,这是我显然希望避免的(7个硬盘,唤醒了功率能上100w,待机21W,定期查询温度=永远无法休眠)。
所以本文用smartctl来操作,读取硬盘的状态。
实现方式:
主要的实现方式是通过python的os库的popen来执行命令行,并将返回的信息进行处理。
1、第一次执行的时候,查询全部硬盘的状态,获取硬盘总数,并知道每个硬盘的具体路径。执行smartctl --scan
root@ur:~# smartctl --scan
/dev/sdb -d scsi # /dev/sdb, SCSI device
/dev/sdc -d scsi # /dev/sdc, SCSI device
/dev/sdd -d scsi # /dev/sdd, SCSI device
/dev/sde -d scsi # /dev/sde, SCSI device
/dev/sdf -d scsi # /dev/sdf, SCSI device
/dev/sdg -d scsi # /dev/sdg, SCSI device
/dev/sdh -d scsi # /dev/sdh, SCSI device
从返回的信息来看,很容易就可以写出python的代码:
res = os.popen('smartctl --scan').read()
lines = res.split('\n')
logging.warning(f'扫描到的硬盘数量为:{len(lines)-1}.')
for i in range(len(lines)-1):
l = lines[i]
loc = l[:8]
hddLoc.append(loc)
hddTemp.append(-1)
这样,hddLOC的长度就是硬盘的数量,其内容就是'/dev/sda'这种每个硬盘的路径。
2、逐个硬盘去查询,对于休眠状态的,不查询温度,避免唤醒硬盘,对于工作中的,查询温度。
#扫描硬盘
DiskStandby = 0
for i in range(len(hddLoc)):
l = hddLoc[i]
#查询硬盘的工作状态
res = os.popen(f'smartctl -n standby {l}').read()
#如果硬盘处于休眠状态,返回的信息里面会包含'STANDBY'字样
if res.find('STANDBY') != -1:
#硬盘在休眠,跳过
logger.info(f'{l} 休眠中.')
hddTemp[i] = -1
DiskStandby += 1
else:
#硬盘上电,查看温度
res = os.popen(f'smartctl -A {l} | grep Temperature ').read()
#定位到硬盘温度的位置
r = res.find('(')
if r != -1:
temp = int(res[r-4:r-1])
hddTemp[i] = temp
logger.info(f'{l} 运行中,温度为:{temp}')
3、计算最高活跃硬盘的温度,并由此计算风扇的应该的转速(通过PI算法)
#最高温度
maxT = max(hddTemp)
#通过最高温度去调整风扇的转速
if maxT > FAN_OPENTH:
spd = (maxT - FAN_OPENTH)*FAN_SPDUPRATIO
if spd > 100 :
spd = 100
else:
spd = 0
这样,就可以通过python获取当前的电脑的硬盘信息以及温度了,设置一个程序,在后台定期运行,例如我的程序是每一分钟会更新一次,算一下要不要调整风扇转速。log信息如下:
2024-03-06 12:03:40,718 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为45℃,风扇转速0%
2024-03-06 12:04:41,662 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为47℃,风扇转速20%
2024-03-06 12:05:42,590 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为45℃,风扇转速0%
2024-03-06 12:06:43,511 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为45℃,风扇转速0%
2024-03-06 12:07:44,446 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为45℃,风扇转速0%
2024-03-06 12:08:45,381 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为45℃,风扇转速0%
2024-03-06 12:09:46,324 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为47℃,风扇转速20%
2024-03-06 12:10:47,256 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为47℃,风扇转速20%
2024-03-06 12:11:48,205 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为48℃,风扇转速30%
2024-03-06 12:12:49,142 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为48℃,风扇转速30%
2024-03-06 12:13:50,081 - __main__ - WARNING - 2个硬盘休眠中,其他硬盘的最高温度为47℃,风扇转速20%
2024-03-06 12:14:50,277 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为46℃,风扇转速10%
2024-03-06 12:15:50,483 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为46℃,风扇转速10%
2024-03-06 12:16:50,700 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为46℃,风扇转速10%
2024-03-06 12:17:50,927 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为46℃,风扇转速10%
2024-03-06 12:18:51,165 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为46℃,风扇转速10%
2024-03-06 12:19:51,391 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为47℃,风扇转速20%
2024-03-06 12:20:51,616 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为47℃,风扇转速20%
2024-03-06 12:21:51,794 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为47℃,风扇转速20%
2024-03-06 12:22:52,016 - __main__ - WARNING - 4个硬盘休眠中,其他硬盘的最高温度为47℃,风扇转速20%
2024-03-06 12:23:52,213 - __main__ - WARNING - 5个硬盘休眠中,其他硬盘的最高温度为44℃,风扇转速0%
但是怎么用这个信息去控制风扇的转速呢?我是利用GD32来做了一个PWM控制器,通过串口将转速发给单片机,单片机实现风扇的转速控制以及实际转速的测量反馈。这个部分的专业知识要求就高一些了,后面我将会再单独更新相关的内容。