web-dev-qa-db-ja.com

タイマーでハードドライブをスタンバイ(スピンダウン)にする方法は?

アイドル状態のときにハードドライブをスピンダウンさせたいのですが、たとえば20分間です。このNASはめったに使用されないため、任意の分数で問題ありません。

私が試したがうまくいかなかったこと:

  • ataidle -S 20 /dev/ada0は単にドライブをただちにスピンダウンし、タイマーは効果がありません。アクセスのためにドライブがスピンバックされると、ドライブは回転したままになります。

  • camcontrol standby /dev/ada0 -t 1200ataidleと同じ動作。

  • FreeNAS UIのストレージ->ディスク-> Adv。 PowerManagerの設定は単にcamcontrolを呼び出すだけで、同様にタイマーは効果がありません。スタンバイを許可する電力設定(127など)が選択されている場合、ドライブはほぼ即座にスピンダウンし(場合によっては8秒後)、アクセスがある場合は常にスピンダウンします。

通常の「しばらく使用しない場合はスタンバイ」動作を取得するにはどうすればよいですか?

FreeBSD 11.2-STABLEを介してFreeNAS 11.2を使用します。ドライブは、4x Samsung 2TB 2.5インチ.T2000LM003`

# smartctl -P show /dev/ada0
smartctl 6.6 2017-11-05 r4594 [FreeBSD 11.2-STABLE AMD64] (local build)
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org

Drive found in smartmontools Database.  Drive identity strings:
MODEL:              ST2000LM003 HN-M201RAD
FIRMWARE:           2BC10007
match smartmontools Drive Database entry:
MODEL REGEXP:       ST(1500|2000)LM0(03|04|06|07|10) HN-M[0-9]*RAD
FIRMWARE REGEXP:    .*
MODEL FAMILY:       Seagate Samsung SpinPoint M9T
ATTRIBUTE OPTIONS:  None preset; no -v options are required.
1
Adam

私はこれを非常に手動で行うことになりました。ドライブアクティビティをチェックし、ドライブがない場合はドライブをスピンダウンするスクリプトを作成し、このスクリプトをcronジョブとしてスケジュールします。

私は、iostatを使用してドライブを設定された期間(私の場合は600秒(10分))監視するアプローチを採用しました。 iostatが使用状況を報告しない場合は、ataidle -s /dev/ada[0123]を呼び出してドライブを一時停止します。このスクリプトを15分ごとに呼び出すようにcronジョブを設定しました:*/15 * * * * spindown_if_idle.sh 600

spindown_if_idle.sh

#!/bin/bash

# argument is the number of seconds to test for drive use, default to 5
if [ -z "$1" ]; then
    SECONDS=5
else
    SECONDS="$1"
fi

function list_ada_drives {
    # emit a list of hard drives, i.e. ada0 ada1 ada2 ...
    iostat -x | grep "ada" | awk '{print $1}'
}

function spindown {
    # for every hard drive use ataidle to place it in standby
    for ADA in $(list_ada_drives); do
        ataidle -s /dev/$ADA
    done
}

function are_drives_used {
    # argument is number of seconds to test over

    # run iostat for the specified number of seconds and ask to report any usage
    # -z means to omit any drives that are idle
    # iostat will print two reports, the first since boot and the second during the interval
    # The first tail and grep strip off the first useless report. The second tail strips off the header
    # The final grep strips off drives we're not interested in
    iostat -x -z -d $SECONDS 2 | tail -n +2 | grep -A5000  "extended" | tail -n +3 | grep "ada" -q
}

if are_drives_used $SECONDS ; then
    echo "Drives are being used"
else
    echo "Drives are idle, going to standby"
    spindown
fi

collectdメトリック

collectdで記録された過去の使用状況をクエリすることで、この10分のブロックを回避しようとしました。 rrdtool fetchを使用して/var/db/collectd/rrd/localhost/disk-ada0に格納されているメトリックを照会しましたが、それらには数分の遅延があります。それらに依存するということは、スクリプトが最近アイドル状態だった場合にアクティブに使用されているドライブをスタンバイする可能性があることを意味します。

ドライブがスピンアップしているかどうかのテスト

次のスクリプトは、各ドライブがアイドル状態か回転中かを報告します。テストに役立ちます。

is_spinning.sh

#!/bin/sh

camcontrol devlist | grep ada | awk -F\( '{print $2'} | awk -F",|\\\\)" '{print $2}' |while read LINE
do
CM=$(camcontrol cmd $LINE -a "E5 00 00 00 00 00 00 00 00 00 00 00" -r - | awk '{print $10}')
if [ "$CM" = "FF" ] ; then
echo "$LINE: SPINNING"
Elif [ "$CM" = "00" ] ; then
echo "$LINE: IDLE"
else
echo "$LINE: UNKNOWN"
fi
done

このフォーラム投稿 に基づいています。

1
Adam

このアイデアをありがとう。私はこの問題に数日間苦しんでいました。私はbashスクリプトの作成に慣れていないため、python3で書き直しました。多分誰かがそれが役に立つと思うでしょう:

import subprocess
import time

drives_to_check = ['ada3', 'ada4', 'ada5']
no_sleep_hours = ['00', '01']
seconds = 600

if time.strftime("%H") in no_sleep_hours:
    exit()

o = subprocess.check_output(f'/usr/sbin/iostat -x -z -d {seconds} 2', Shell=True)

for drive in drives_to_check:
    if drive not in o.decode().split('extended')[-1]:
        p = subprocess.check_output(f'/sbin/camcontrol cmd {drive} -a "E5 00 00 00 00 00 00 00 00 00 00 00" -r -', Shell=True)
        if p.decode()[27:29] != '00':
            q = subprocess.check_output(f'/usr/local/sbin/ataidle -s /dev/{drive}', Shell=True)

私の小さなアドオンは次のとおりです。スクリプトを実行したくない場合は、no_sleep_hoursに時間を追加できます。また、チェックするドライブを「drives_to_check」に追加して、スピンダウンを実行しないドライブを除外できるようにする必要があります。おそらく、iostatとataidleのパスを調整する必要があります。これらは、FreeNASで使用されるパスです。パスは、which adaidleまたはwhich iostatで見つけることができます。 */15 * * * * /usr/local/bin/python3 /path/to/the/folder/check_disk_usage_and_spindown.pyでcronに追加できます

1
pelipro