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에서 meuh의 솔루션을 다시 구현했습니다.
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)
이 솔루션은 meuh의 솔루션만큼 기술적으로 정확하지는 않지만 Perl을 구문 분석할 수 없으며 내 설정에서는 제대로 작동하는 것 같습니다. 코드를 직접 작성하고 싶습니다.