Raspberry Piに接続されている外部WD Redディスクが回転しすぎます。

Raspberry Piに接続されている外部WD Redディスクが回転しすぎます。

Raspberry Piに接続された2つの外部WD Redハードドライブがあります。
2分後に回転が始まります。これは迷惑なほど速く、常に回転するのを待つ必要があります。

hdparmWDディスクでは機能しないことを読みました。テストしましたが、hdparm -I | grep level結果は出ませんでした。

これについて読みましたhd-idleが、私が理解したのはスタンバイモードに切り替えられないディスクに役立ちます。

どうして増加する待ち時間を超えましたか?

編集:私はこれをテストしましたhdparm -Sが、影響はありませんでした。

答え1

逆の操作を行うために、独自のhd-idleバージョンを作成できます。つまり、ディスクドライブが通常アイドル状態になるまで、いくつかのアクセスを実行してディスクドライブを目覚めたままにします。ただし、実際に置く必要があるときとディスクをスリープ状態にするときを明確に区別する必要があります。

これはPerlスクリプトを使った試みです。これを実行するためにルートになる必要はありませんが、目を覚ますために読み取り可能なディスクにいくつかのファイルを設定する必要があります。 hd-idleのように/sys/。適切な時間内にI / O操作が完了しない場合は、フラグを使用してKeep-Awakeファイルから小さな読み取りを実行して、O_DIRECT実際のI / Oが完了したことを確認してください。次のポーリングで他の実際のI / Oが発生したかどうかを検出できるように、読み取り/書き込み統計の合計に1を追加するだけです。

#!/usr/bin/perl
# stop standby of idle disc which doesnt support hdparm -S 12
# for stat fields see kernel src Documentation/iostats.txt
# https://unix.stackexchange.com/a/422138/119298
use strict;
use Fcntl;

my $device = 'sda';
my $filename = '/mnt/myfs/lost+found/tickle';

# create tickle file for test. or use any readonly non-empty file
if(! -s $filename){
    open(FILE,">$filename") or die $!;
    print FILE "used to keep disk from sleeping\n" or die $!;
    close(FILE) or die $!;
}
sysopen(FILE,$filename,O_RDONLY|O_DIRECT) or die $!;

my $minidle = 2*60;  # seconds of real idle before need to tweak awake
my $maxidle = 10*60; # seconds of false idle before allow to sleep
open(STAT,"/sys/block/$device/stat") or die;
my ($lasttot,$timechanged,$done);

# create block aligned buffer for O_DIRECT read
my $bufsize = 4096;
my $align = 512;
my $buf = 'x' x ($align+$bufsize);
my $offset = unpack("J", pack "p", $buf) % $align;
$offset = $align-$offset if $offset;

while(){
    my @fields = split(' ',<STAT>);
    # fields: 0 reads completed ok, 4 writes completed ok.  may wrap
    my $tot = $fields[0]+$fields[4];
    if($tot==$lasttot){
        my $idle = time()-$timechanged;
        print "$device idle $idle secs\n";
        if($done){
            # let it sleep some more
        }elsif($idle>=$maxidle){ # let it really sleep now
            print "$device sleep now after $idle secs\n";
            $done = 1;  
        }elsif($idle>=$minidle){ # tickle to stay awake
            sysseek(FILE,0,Fcntl::SEEK_SET)==0 or die $!;
            sysread(FILE,$buf,$bufsize,$offset)>0 or die $!;
            $lasttot++;
        } # else builtin hardware timeout not reached yet
    }else{
        $timechanged = time();
        $lasttot = $tot;
        $done = 0;
    }
    seek(STAT,0,0);
    sleep(55);
}

$deviceディスク名、$filename空でない既存のファイル名、またはディスクに作成できるファイル名に設定する必要があります。$minidleディスクが通常、それ自体がアイドル状態にある時間と$maxidle強制的にアクティブな状態を維持する時間が必要です。ポーリング時間は最終
設定にあります。sleep()

答え2

しかし、ヤヨンの答えこれは質問に対する正解です。私の実際の状況はソフトウェア攻撃に関連しており、私は汚いミレニアル世代です。
私は読み取りの代わりに書き込みを使用してPythonでmiuhのソリューションを再実装しました。

import time
import datetime
import os

statFile = "/sys/block/<yourdevicehere>/stat"
logFile = "/some/file/on/another/drive.log"
dummyFile = "/some/file/on/drive/in/question"
updateInterval = 60 # seconds
keepAwakeTime = 30 * 60 # seconds
keepAwakeIOCount = 12 # empirically "proven"

# Clear the log file
open(logFile, "w").close()

def getIOCount():
    with open(statFile, "r") as fobj:
        fileContents = fobj.read()
    stats = fileContents.split()
    readCount = int(stats[0])
    writeCount = int(stats[4])
    return readCount + writeCount

# ==== main loop ==== #

maxIODiff = 0
averageIODiff = 0
diffCount = 0

previousIOCount = getIOCount()
timer = 0
while True:
    ioCount = getIOCount()
    if ioCount > previousIOCount:
        timer = keepAwakeTime

    ioDiff = ioCount - previousIOCount
    if ioDiff > maxIODiff:
        maxIODiff = ioDiff
    averageIODiff = (averageIODiff * diffCount + ioDiff) / (diffCount + 1)
    diffCount += 1

    previousIOCount = ioCount

    if timer > 0:
        line = str(ioDiff) + " " + str(maxIODiff) + " " + str(averageIODiff) + " " + datetime.datetime.now().strftime("%H:%M:%S") + "\n"
        with open(dummyFile, "w") as dummy:
            dummy.write(line)
            dummy.flush()
            os.fsync(dummy.fileno()),
        with open(logFile, "a") as log:
            log.write(line)
        previousIOCount += keepAwakeIOCount

    timer -= updateInterval
    time.sleep(updateInterval)

このソリューションはmihのソリューションほど技術的に正確ではありませんが、Perlを解析できず、私の設定ではうまくいくようです。コードを直接書きたいです。

関連情報