外付けハードディスクの回転を止める

sheevaplugに付けた外付けHDDを勝手に止めるようにする。
http://www.nslu2-linux.org/wiki/FAQ/SpinDownUSBHarddisks#method3
ほとんどここにあったスクリプトのパクリ
ポイントはいくつかあるが、、、

まずはsdparmを使う点。
syncだったところをsdparm –command=sync
scsi-idleをsdparm –command=stop にする。
(–command=syncしたあとじゃないと、stopしても止まらないので注意。)

次に、ディスクのデバイスファイルは、さしなおしたりしたときに毎回同じにふられるとは限らないので、とりあえずマウントポイントから、起動時にmountコマンドをつかってデバイスファイルに関連付け。(/dev/disk/by-uuidからls -lでリンク先を見ればデバイスファイル名を取れるが、ディスク入れ替え時にいちいち対応しないといけないので、、、ちょっと迷ったがこっちの方式で利用。)

最後に、一つのスクリプトで複数のディスクを(何個でも)扱えるようにした点。
ま、見ての通り。

スクリプトはこんな感じ

#!/bin/sh
mount=(/mnt/disk /mnt/backup)
num=${#mount[@]}
interval=4000
for ((i=0; i < num;i++)); do
  tmp=(`mount |grep ${mount[i]}`)
  [ x"$tmp" = x ] && continue
  tmp1=${tmp[0]#/dev/}
  disk[i]=${tmp1%[0-9]}
  state[i]=`grep " ${disk[i]} " /proc/diskstats`
  up[i]=1
  count[i]=$interval
done
while [ true ]; do
  sleep 600
  for ((i=0;i < num;i++)); do
    count[i]=$((${count[i]}-600))
    newstate[i]=`grep " ${disk[i]} " /proc/diskstats`
    [ `echo ${newstate[i]} | wc -l` -eq 1 ] || continue
    if [ "${state[i]}" = "${newstate[i]}" ]; then
      if [ ${count[i]} -lt 0 ]; then
        count[i]=$interval
        if [ ${up[i]} -eq 1 ]; then
          echo -e "spin-down: /dev/${disk[i]}"
          sdparm --command=sync /dev/${disk[i]}
          state[i]=`grep " ${disk[i]} " /proc/diskstats`
          sdparm --command=stop /dev/${disk[i]}
          up[i]=0
        fi
      fi
    else
      echo -e "drive is up: /dev/${disk[i]}"
      count[i]=$interval
      state[i]="${newstate[i]}"
      up[i]=1
    fi
  done # for i
done # for while loop

で、このスクリプトを適当に保存して、rc.localからバックグラウンドで起動する。
(最初は多重起動対策とか考えないといけないのかな?とか思っていたが、rc.localは、起動時に/var/lock以下にロックファイルを作成するため、ランレベル変更時など、さらに起動されることはないようだ(/etc/rc参照)
起動時にはK*を殺してからS*を起動するというのは知っていたが、この仕組みは知らなかったので、ちょっと迷った。2重起動対策はしなくてOK)

その後、sdparmにsda1など、パーティション番号の数字?を入れると/var/log/messagesに sending ioctl 2285 to a partition! というのがたくさん出てくるので、最後の数字をとるように変えました。

コメントを残す