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에서 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을 구문 분석할 수 없으며 내 설정에서는 제대로 작동하는 것 같습니다. 코드를 직접 작성하고 싶습니다.

관련 정보