Raspberry Piに接続された2つの外部WD Redハードドライブがあります。
2分後に回転が始まります。これは迷惑なほど速く、常に回転するのを待つ必要があります。
hdparm
WDディスクでは機能しないことを読みました。テストしましたが、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を解析できず、私の設定ではうまくいくようです。コードを直接書きたいです。