浅谈OpenWrt的硬盘休眠问题

2021-06-18 00:11:50 7点赞 35收藏 5评论

创作立场声明:非专业人士创作,大佬轻拍

最近在软路由上加装了一块3.5寸的机械硬盘,算上之前已经挂载的一块仓库盘,软路由上共有两块SATA硬盘。根据插座上的功耗计显示,一块机械硬盘的运行功耗大约在5瓦左右。因此我打算设置硬盘超时休眠来降低功耗和噪音。

这本是一件简单的事情,因为OpenWrt的luci界面就可以直接操作。

浅谈OpenWrt的硬盘休眠问题

但让人郁闷的是,luci界面只能对一块硬盘设置超时休眠。可能是因为软路由相比专用NAS,挂载多硬盘的场景不多,一般只会连接一块下载盘,所以这项功能很弱鸡。

看来需要在后台进行一些设置,或者借助第三方的磁盘管理工具了。

大多部署在服务器端的Linux系统因为应用场景的关系,并不太需要硬盘休眠功能。而面向个人用户的众多发行版中,能够操作硬盘休眠的工具也不多,最常见是hd-idle,hdparm和sdparm。

OpenWrt默认工具就是hd-idle,软件仓库里也能找到hdparm,而sdparm已经被抛弃了。

opkg update

opkg install hdparm

hd-idle小巧精悍,操作简便;而支持APM的hdparm在功能上似乎更加丰富一些。当然,能够起作用,才是最终选择的理由。

参考了许多使用教程和“troubleshooting case”后,我觉得“起作用”的标准应该如下:

1)硬盘在超时(timeout)无访问后,会自动进入休眠状态(standby);

2)休眠硬盘在被唤醒后(active/idle),依然能够重复进入状态1)

3)系统重启后,能够进入状态1)和2)

首先测试程序能否进行休眠操作:

hd-idle -t sda

hdparm -y /dev/sda #注意不要输入-Y参数,是进入睡眠模式(sleep),硬盘完全断电

看到功率计数字降下来5瓦;或者在luci的磁盘管理页面下,也能查看休眠状态;再或者使用S.M.A.R.T.工具。

smartctl -n standby /dev/sdx

#查看电源状态且不会唤醒休眠磁盘,输出 Device is in ACTIVE or IDLE mode 或 Device is in STANDBY mode, exit(2)

目前大多数磁盘都能支持hd-idle和hdparm。

然后设置超时休眠:

hd-idle -i 0 -a sda -i 1200 -a sdb -i 1200 #-a参数指定硬盘名称,-i指定休眠时间秒

hdparm -S 240 /dev/sda

hdparm -S 240 /dev/sdb #1个数值对应5秒

那么问题来了~~

我测试了一段时间,不管用哪个工具,休眠设置有时生效,有时无效。

究其原因,多数教程只是讲解怎样用参数命令来设置,但这是一次性操作,休眠后再被唤醒就不起作用了;或者单纯把命令写入启动加载文件rc.local,系统重启后依然是一次性操作;再或者把命令写入crontab按时执行,我不确定这么做有没有效果,但如果到了设定周期时,硬盘正在高速读写会怎样?吃着火锅唱着歌然后突然就被休眠了?自动休眠的初衷是有读写就工作,没读写且超时才休眠,并不是时刻准备着要休眠。

解决这个问题恐怕需要编写和加载正确的程序配置文件。

先来查找hdparm的配置文件:

root@OpenWrt:~# find / -name hdparm

/overlay/upper/sbin/hdparm

/sbin/hdparm

貌似OpenWrt上安装的hdparm是个精简版,并没有默认配置文件/etc/hdparm.conf,而不同Linux发行版上的配置文件也不相同,重写一个似乎毫无头绪。放弃~~

再来查找hd-idle的配置文件:

root@OpenWrt:~# find / -name hd-idle

/etc/config/hd-idle

/etc/init.d/hd-idle

/overlay/upper/etc/config/hd-idle

/rom/etc/config/hd-idle

/rom/etc/init.d/hd-idle

/rom/usr/bin/hd-idle

/usr/bin/hd-idle

其中可编辑的配置文件只有/etc/config/hd-idle和/etc/init.d/hd-idle,其他是无需编辑的配置文件(/overlay和/rom)和无法编辑的二进制文件 (/usr/bin)。配置源文件见:

hd-idle.config

hd-idle.init

修改配置文件/etc/config/hd-idle ,为第二块硬盘增加一个字段:

config 'hd-idle'

option 'disk' 'sda'

option 'enabled' '1' #如果是关闭状态'0',可以删去

option 'idle_time_unit' 'minutes'

option 'idle_time_interval' '20'


config 'hd-idle'

option 'disk' 'sdb'

option 'enabled' '1' #如果是关闭状态'0',可以删去

option 'idle_time_unit' 'minutes'

option 'idle_time_interval' '20'

保存后重启hd-idle:

/etc/init.d/hd-idle enable

/etc/init.d/hd-idle start

生效后能够找到相关进程:

root@OpenWrt:~# ps | grep hd-idle

28553 root 716 S /usr/bin/hd-idle -d -i 0 -a sda -i 1200 -a sdb -i 1200

28577 root 1096 S grep hd-idle

这里忍不住吐槽一下,手册上讲硬盘名称也可使用symlinks,即/dev/disk/by-id/...,好处是插拔某些存储设备造成硬盘路径改变后,不会影响休眠设置。但我试过很多命令,除了能看到磁盘分区的uuid之外,没法查到块设备的id。系统也无法安装udev,只能作罢。

发现配置成功后,luci界面的“硬盘休眠”也能显示两块硬盘了。

还是原生工具给力还是原生工具给力

那么现在硬盘休眠能否满足上文的“起作用”三标准呢?虽然确实有硬盘休眠/唤醒事件,但是查看系统日志并没有相应记录,而程序命令也没有在默认目录生成日志文件

hd-idle -l /var/log/hd-idle.log

所以还是有哪里不对。

留意到上文中ps | grep hd-idle的输出信息了吗?

28553 root 716 S /usr/bin/hd-idle -d -i 0 -a sda -i 1200 -a sdb -i 1200

其中的-d参数,按照手册的说明:

-d Debug mode. This will prevent hd-idle from becoming a daemon and print debugging info to stdout/stderr

调试模式会阻止hd-idle成为守护进程及标准信息输出,这应该就是日志无法生成的原因。

找到这个参数的由来,在/etc/init.d/hd-idle配置文件中:

...

hdidle_append() {

[ "$2" = 0 ] || return


[ "$enabled" -gt 0 ] || return


if [ "$numdisks" = "0" ]; then

procd_open_instance

procd_set_param command /usr/bin/hd-idle

procd_append_param command -d -i 0

fi

procd_append_param command -a $disk

procd_append_param command -i "$(compute_seconds $idle_time_interval $idle_time_unit)"

numdisks=$(( numdisks + 1 ))

...

删去procd_append_param command -d -i 0中的-d,重启hd-idle后再次执行hd-idle -l /var/log/hd-idle.log。 这次可以看到进程数变多了:

root@OpenWrt:~# ps | grep hd-idle

2385 root 1096 S grep hd-idle

4014 root 716 S /usr/bin/hd-idle -i 0 -a sda -i 1800 -a sdb -i 1800

6393 root 716 S /usr/bin/hd-idle -i 0 -a sda -i 1800 -a sdb -i 1800

7610 root 716 S /usr/bin/hd-idle -i 0 -a sda -i 1800 -a sdb -i 1800

8342 root 716 S /usr/bin/hd-idle -i 0 -a sda -i 1800 -a sdb -i 1800

8669 root 716 S /usr/bin/hd-idle -i 0 -a sda -i 1800 -a sdb -i 1800

10241 root 716 S /usr/bin/hd-idle -i 0 -a sda -i 1800 -a sdb -i 1800

12490 root 720 S hd-idle -l /var/log/hd-idle.log

查看日志(日志只有在唤醒活动后才会生成,并且有一定延迟):

root@OpenWrt:~# cat /var/log/hd-idle.log

date: 2021-06-17, time: 01:01:42, disk: sdc, running: 603, stopped: 2820

date: 2021-06-17, time: 08:06:43, disk: sdb, running: 600, stopped: 28324

date: 2021-06-17, time: 08:06:44, disk: sda, running: 600, stopped: 28325

date: 2021-06-17, time: 08:06:45, disk: sdc, running: 601, stopped: 24902

date: 2021-06-17, time: 08:33:47, disk: sdc, running: 782, stopped: 840

date: 2021-06-17, time: 21:32:48, disk: sdc, running: 601, stopped: 46140

date: 2021-06-17, time: 21:39:49, disk: sdb, running: 603, stopped: 48183

date: 2021-06-17, time: 21:39:50, disk: sda, running: 603, stopped: 48183

date: 2021-06-17, time: 22:03:54, disk: sdc, running: 1446, stopped: 420

date: 2021-06-17, time: 22:15:55, disk: sdb, running: 1023, stopped: 1143

date: 2021-06-17, time: 22:15:56, disk: sda, running: 1022, stopped: 1144

date: 2021-06-17, time: 22:15:57, disk: sdc, running: 601, stopped: 122

讲真这个日志我也看不大懂。Gayhub上有个项目是加强版的hd-idle(不是OpenWrt上预装的这个),开发者老哥专门解释了关于日志的内容。

How to understand logs #22

仅看sda,sdb的时间点和stopped值,能够对应上休眠时间:截至早晨08:06:44,夜间共休眠28325/60/60=7.868h,换算开始休眠时间为凌晨00:14:39;截至晚上21:39:50,白天共休眠48183/60/60=13.384h,换算开始休眠时间为早晨08:16:48。结合上面的早晨日志输出时间也就是唤醒时间08:06:44,唤醒后只运行了10分钟?这就是running:600的由来?难道30分钟的超时设置没有生效吗?

不管那么多了,反正“起作用”的几条标准,基本上满足了。不需要经常查看日志的话,重启即可,毕竟日志的读写也可能影响休眠状态。

展开 收起

Xiaomi 小米 AX3000T 双频3000M 家用千兆Mesh路由器 Wi-Fi 6 白色 单个装

Xiaomi 小米 AX3000T 双频3000M 家用千兆Mesh路由器 Wi-Fi 6 白色 单个装

99元起

Xiaomi 小米 BE6500 Pro 双频6500M 家用千兆Mesh无线路由器 Wi-Fi 7

Xiaomi 小米 BE6500 Pro 双频6500M 家用千兆Mesh无线路由器 Wi-Fi 7

535元起

Ruijie 锐捷 雪豹 X30E 双频3000M 家用千兆Mesh无线路由器 Wi-Fi 6 白色 单个装

Ruijie 锐捷 雪豹 X30E 双频3000M 家用千兆Mesh无线路由器 Wi-Fi 6 白色 单个装

159元起

ZTE 中兴 AX3000 巡天版 双频3000M 家用千兆Mesh无线路由器 Wi-Fi 6 单个装 白色

ZTE 中兴 AX3000 巡天版 双频3000M 家用千兆Mesh无线路由器 Wi-Fi 6 单个装 白色

164元起

Xiaomi 小米 BE3600 2.5G版 3600M 双频千兆家用无线路由器 Wi-Fi 7 白色

Xiaomi 小米 BE3600 2.5G版 3600M 双频千兆家用无线路由器 Wi-Fi 7 白色

229元起

Redmi 红米 AX6000 双频5952M 家用千兆Mesh无线路由器 Wi-Fi 6 单个装黑色

Redmi 红米 AX6000 双频5952M 家用千兆Mesh无线路由器 Wi-Fi 6 单个装黑色

329元起

ASUS 华硕 RT-BE88U 双频7200M 家用Mesh无线路由器 Wi-Fi 7 黑色 单个装

ASUS 华硕 RT-BE88U 双频7200M 家用Mesh无线路由器 Wi-Fi 7 黑色 单个装

1999元起

Xiaomi 小米 AX6000 双频6000M 家用千兆Mesh无线路由器 Wi-Fi 6 单个装 黑色

Xiaomi 小米 AX6000 双频6000M 家用千兆Mesh无线路由器 Wi-Fi 6 单个装 黑色

299元起

HUAWEI 华为 BE3 Pro 双频3000M 千兆家用路由器 Wi-Fi 7 黑色

HUAWEI 华为 BE3 Pro 双频3000M 千兆家用路由器 Wi-Fi 7 黑色

253.55元起

Xiaomi 小米 BE7000 三频千兆Mesh无线路由器 Wi-Fi 7

Xiaomi 小米 BE7000 三频千兆Mesh无线路由器 Wi-Fi 7

406元起

HUAWEI 华为 AX2 Pro 双频1500M 家用千兆无线路由器 Wi-Fi 6 白色

HUAWEI 华为 AX2 Pro 双频1500M 家用千兆无线路由器 Wi-Fi 6 白色

132元起

ZTE 中兴 问天BE7200Pro+ 双频7200M 家用千兆Mesh无线路由器 WiFi 7 黑色

ZTE 中兴 问天BE7200Pro+ 双频7200M 家用千兆Mesh无线路由器 WiFi 7 黑色

579元起

TP-LINK 普联 BE5100 双频5100M 家用千兆Mesh无线路由器 Wi-Fi 7 黑色 单个装

TP-LINK 普联 BE5100 双频5100M 家用千兆Mesh无线路由器 Wi-Fi 7 黑色 单个装

279元起

TP-LINK 普联 飞流系列 TL-XDR5480 易展Turbo版 双频5400M 家用千兆Mesh无线路由器 WiFi 6 单个装 灰色

TP-LINK 普联 飞流系列 TL-XDR5480 易展Turbo版 双频5400M 家用千兆Mesh无线路由器 WiFi 6 单个装 灰色

369元起

ZTE 中兴 巡天AX3000Pro+ 双频3000M 家用千兆Mesh无线路由器 Wi-Fi 6 白色 单个装

ZTE 中兴 巡天AX3000Pro+ 双频3000M 家用千兆Mesh无线路由器 Wi-Fi 6 白色 单个装

269元起

HUAWEI 华为 Q6 网线版 双频3000M 千兆Mes无线分布式路由器 Wi-Fi 6 一母三子装 白色

HUAWEI 华为 Q6 网线版 双频3000M 千兆Mes无线分布式路由器 Wi-Fi 6 一母三子装 白色

408.8元起
5评论

  • 精彩
  • 最新
  • 多谢,之前曾经想自己实现硬盘按需访问,无访问的时候自动休眠,但最后没有实现,您的文章很有启发。

    校验提示文案

    提交
    如果不是OpenWrt其实这个功能很容易实现。现在不完美的地方是进入休眠的时间太短了,理想休眠时间是30分钟,实际上10分钟就休眠了

    校验提示文案

    提交
    对,休眠时间太短容易频繁唤醒

    校验提示文案

    提交
    收起所有回复
  • 想起了辐射

    校验提示文案

    提交
  • 666

    校验提示文案

    提交
提示信息

取消
确认
评论举报

相关好价推荐
查看更多好价

相关文章推荐

更多精彩文章
更多精彩文章
最新文章 热门文章
35
扫一下,分享更方便,购买更轻松