Skip to content
Erning.write()
Go back

USB 硬盘的固定设备名和自动休眠

AirPort Extreme 可以外接 USB 硬盘提供文件服务,但是和它的路由功能一样,都不够满足我的需求。而作为穿墙路由器的华硕小机器有 4 个 USB 口,我还用它兼作文件服务器,提供 Samba 和 NFS。

但是 Gentoo 在这里遇到两个小问题。

第一个问题,USB 硬盘是可以热拔插的,由于载入顺序的问题,每个硬盘的设备名称可能会变化。例如这个机器自带一个读卡器,在没有外挂 USB 硬盘时启动后设备名为 /dev/sdb。之后插入 USB 硬盘,USB 硬盘的设备名为 /dev/sdc。但是如果挂着 USB 硬盘启动,这两个设备的设备名就正好反过来了。我希望设备名是固定的。

第二个问题,USB 硬盘长时间不访问的时候不会自动停下来,这样既不省电也不利于延长硬盘的寿命。我希望在不用的时候它可以休眠。

设备名的问题可以用 udev 的 rules 解决。我加了一个 udev 配置文件 /etc/udev/rules.d/99-external-storages.rules

KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="0158", ATTRS{serial}=="20071114173400000", SYMLINK+="cardreader%n"
KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1bcf", ATTRS{idProduct}=="0c31", ATTRS{serial}=="20090717090A", SYMLINK+="storage/neso%n"

这样给内置的读卡器添加了一个设备名的符号链接 /dev/cardreader;给我的 NESO 1T 硬盘添加了设备名符号链接 /dev/storage/neso。用固定名称访问设备的问题就解决了。

第二个问题稍微复杂些,一直没找到方便的方法。laptop-mode-tools 也没能满足我的要求。一番搜索后找到 sdparm 可以用来控制 USB 硬盘,还有一段 Perl 脚本用来调度 sdparm。这样就可以满足我的需求了。脚本的原始出处我给忘了,这里我稍微修改了一点,增加对设备名符号链接的支持。

#!/usr/bin/perl -w
use File::Basename;
use Cwd 'abs_path';

$statfile = "/proc/diskstats";
die "$0: Cannot read $statfile\n" unless -r $statfile;

$| = 1;
($disk, $interval) = (@ARGV);

if (-l $disk) {
    $original_disk = $disk;
    while (-l $disk) {
        $disk = readlink $disk;
    }
    $disk = dirname($original_disk) . "/" . $disk;
    $disk = abs_path($disk);
}

$disk =~ s,/dev/,,;
print "$0: disk: $disk, interval: $interval\n";

$halted_data = $last_seen = '';
while (1) {
  open(STATUS, $statfile);
  ($_) = grep(/^\s+\d+\s+\d+\s+$disk\s/o, <STATUS>);
  close STATUS;

  if ($last_seen eq $_ && $halted_data ne $_) {
    print "Spinning down: $disk\n";
    system "sync";
    system "sdparm", "--command=stop", "/dev/$disk";
    $halted_data = $_;
  }
  $last_seen = $_;
  sleep $interval;
}

最后在启动脚本里加上

ebegin "    - Spindown USB HD"
nohup /usr/local/sbin/spindown-usbhd /dev/storage/neso 1200 >> /var/log/spindown-usbhd.log 2>&1 &
eend $?

好了,20 分钟这块硬盘没有读写之后自动休眠。


Share this post on:

Previous Post
自建动态域名解析服务
Next Post
在 VMware ESXi 上开启 SSH 服务