![在 Linux(树莓派)上强制关闭外部硬盘](https://linux22.com/image/1379896/%E5%9C%A8%20Linux%EF%BC%88%E6%A0%91%E8%8E%93%E6%B4%BE%EF%BC%89%E4%B8%8A%E5%BC%BA%E5%88%B6%E5%85%B3%E9%97%AD%E5%A4%96%E9%83%A8%E7%A1%AC%E7%9B%98.png)
我目前正在使用 Raspberry Pi 设置家庭服务器,并通过 USB 连接外部硬盘。但是,我的硬盘在空闲时永远不会停止旋转。
我已经尝试了提供的提示raspberrypi.org ...没有任何成功。
1.)
sudo hdparm -S5 /dev/sda
返回
/dev/sda:
setting standby to 5 (25 seconds)
SG_IO: bad/missing sense data, sb[]: 70 00 04 00 00 00 00 0a 00 00 00 00 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2.)
sudo hdparm -y /dev/sda
返回
/dev/sda:
issuing standby command
SG_IO: bad/missing sense data, sb[]: 70 00 04 00 00 00 00 0a 00 00 00 00 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...和 3.)
sudo sdparm --flexible --command=stop /dev/sda
返回
/dev/sda: HDD 1234
...无需降低驱动器的转速。
我使用以下硬件:
- Inateck FDU3C-2 双端口 USB 3.0 HDD 扩展坞
- 西部数据 WD10EZRX 绿色 1TB
发送的旋转减速信号有可能在某处被覆盖/丢失/忽略吗?
答案1
我对 hd-idle 不太满意;它运行了但没有起作用。我最终写了下面的脚本:
#!/bin/bash
# This script looks for recent disk access, and if nothing has changed, puts /dev/"drive" into spindown mode.
# This should be used only is the hdparm power management function is not working.
# Call this script with cron or manually as desired
#
#
#
# Change which drive this script looks at by changing the drive variable below:
drive="sda"
#
#
current=`date`
caller=$(ps ax | grep "^ *$PPID" | awk '{print $NF}')
filename="/tmp/diskaccess.txt"
if [ -f "$filename" ]; then
stat_old=`cat "$filename" | tr -dc "[:digit:]"`
stat_new=`cat /sys/block/"$drive"/stat | tr -dc "[:digit:]"`
if [ "$stat_old" == "$stat_new" ]; then
stat="0"
echo "The disk hasn't been used; spinning down /dev/$drive"
echo $stat_old
hdparm -y /dev/$drive > /dev/null
else
stat="1"
echo $stat_old
echo $stat_new
echo "The drive has been used..."
echo $stat_new > $filename
fi
else
echo "/tmp/diskaccess.txt file does not exist; creating it now."
echo $stat_new > $filename
fi
echo $stat " - " $drive " - " $current " - by: " $caller >> /tmp/diskaccesslog.txt
答案2
是的,这是可能的,但需要一些定制的开发工作,而且并非易事,并且代码将特定于外壳内部的 USB->SATA 桥接芯片。
问题是,USB 桥接器的作用不只是电气转换器。USB 连接的 HDD 模拟具有不同命令集的 SCSI 驱动器。虽然标准读/写/寻道命令始终会转换,但更奇特的启动/停止命令则不会转换。大多数芯片不会这样做。此外,没有通用的芯片级 API。所以如果我编写代码,我必须有 USB 桥接器芯片的编程手册。
底线是,除非您了解芯片的编程细节,并且熟悉 ATA 和 SCSI 指令集以及封装直通命令,否则您只能放弃。工作量太大,而且没有标准。
答案3
您发送的信号完全有可能被忽略。您没有提供
sudo hdparm -I /dev/sdX
它会告诉我们磁盘的功能,但是许多磁盘根本不响应这些命令。
幸运的是,有一个非常方便的实用程序,hd-idle,你可以从这里下载,允许您在指定的一段时间后强制磁盘旋转停止。该程序是专门为 Debian 开发的(但它通常适用于 Linux),因此它的安装对您来说应该非常容易。我只是希望它也能在 ARM 架构上运行,这是我无法测试的。
编辑:它在 raspbian 上正确编译并安装。
答案4
我对 user300457 发布的很好的脚本做了一些修改。
变化:
- 调用脚本时,添加驱动器作为参数(例如“sdb”)。这使脚本可以控制多个驱动器(只需将具有不同驱动器的脚本多次添加到 crontab 即可)。
- 我需要能够检查驱动器是否处于待机模式(在另一个不相关的应用程序中),但在检查状态时,原始脚本认为驱动器已发生变化。这实际上意味着,如果定期检查状态,驱动器将永远不会停止旋转。因此...脚本已更新,以便能够处理检查当前状态。
- /var/log/hdd_spindown.log 中会生成更清晰的日志文件,仅跟踪驱动器旋转和停止的时间
下面包含该脚本,并附有描述如何使用它的注释。
我希望这对某些人有用:-)
#!/bin/bash
# This script looks for recent disk access, and if nothing has changed, puts the drive into spindown mode
#
# 1. Copy the script to /root:
# sudo cp hdd_spindown.sh /root
#
# 2. Add the script to crontab:
# sudo crontab -e
#
# 3. Add the following line to the crontab:
# */30 * * * * /root/hdd_spindown.sh >> /var/log/hdd_spindown.log <drive name> 2>&1
# where <drive name> could be "sda", "sdb" etc.
#
# 4. Reload crontab:
# sudo service cron reload
#
# This will run the script every 30 minutes - i.e. spin down the drive when not being accessed for 30 to 60 minutes
#
# A file logging the spinups/downs is created in /var/log/hdd_spindown.log
drive="$1"
current_spin_state=$(/usr/sbin/hdparm -C /dev/$drive | awk '/state/{print $NF}')
# If the drive is already in standby mode, there is no need to do more
if [ "$current_spin_state" != "standby" ]; then
current_time=$(date +"%Y-%m-%d %T")
script_name=$(basename -- "$0")
filename="/tmp/${script_name}_${drive}_status.txt"
current_sectors=$(cat /sys/block/"$drive"/stat | awk '{print $3,$7}')
if [ -f "$filename" ]; then
previous_drive_status=$(cat "$filename")
previous_spin_state=$(echo $previous_drive_status | awk '{print $1}')
previous_sectors=$(echo $previous_drive_status | awk '{print $2,$3}')
# If the drive has just spun up store new state and add to log
if [ "$current_spin_state" != "$previous_spin_state" ]; then
echo "$current_time /dev/$drive has spun up since the last check"
echo "$current_spin_state $current_sectors" > $filename
else
# Check if drive sectors have been read or written to
if [ "$current_sectors" == "$previous_sectors" ]; then
# If nothing changed, spin down the drive
echo "$current_time Spinning down /dev/$drive"
/usr/sbin/hdparm -y /dev/$drive > /dev/null
echo "standby $current_sectors" > $filename
else
# If something changed, just store the new drive status
echo "$current_spin_state $current_sectors" > $filename
fi
fi
else
echo "$current_time File $filename does not exist - creating it now"
echo "$current_spin_state $current_sectors" > $filename
fi
fi