Você pode escrever sua própria versão do hd-idle que faz o oposto, ou seja, faz um keep-awake fazendo algum acesso na unidade de disco antes que ele normalmente queira ficar ocioso. Mas você obviamente precisa distinguir quando realmente deixar ir e ter o disco dormindo.
Aqui está uma tentativa com um script perl. Você não precisa ser root para executá-lo, mas você precisa configurar algum arquivo no disco que você pode ler para fazer o keep-awake. Como o hd-idle, ele pesquisa as estatísticas de leitura / gravação do disco em /sys/
. Quando nenhuma E / S tiver sido feita pelo tempo apropriado, uma pequena leitura é feita a partir do arquivo keep-awake usando o flag O_DIRECT
para garantir que uma E / S real seja feita. Isso deve apenas adicionar 1 ao total de estatísticas de leitura / gravação, para que possamos detectar se alguma outra E / S real também aconteceu na próxima pesquisa.
#!/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);
}
Você precisa definir $device
para o nome do disco e $filename
para o nome de um arquivo não vazio existente ou de um arquivo que possa ser criado no disco. Em $minidle
, precisamos do tempo em que o disco normalmente fica inativo sozinho e em $maxidle
o tempo que desejamos.
forçá-lo a permanecer ativo. O tempo de pesquisa é definido no sleep()
no final.