Tenho várias máquinas Ubuntu com SSD e disco rígido tradicional, onde o disco rígido é usado apenas ocasionalmente.
Por motivos de redução de ruído, calor e consumo de energia, além de prolongar a vida útil do disco rígido, gostaria de desligá-lo a cada inicialização e ativá-lo somente quando necessário.
hdparm -y
(ou -Y
) funciona muito bem na linha de comando e faz exatamente o que eu quero.
Mas escrever um serviço systemd para execução hdparm
não funciona. Para ser mais preciso: funciona, e o disco realmente entra em suspensão (como mostra a depuração), mas é imediatamente acordado novamente (e permanece acordado), porque há algo no sistema que acessa os discos rígidos (e assim desperta it) no final do processo de inicialização do systemd.
Então, como posso colocar um hdparm -y
no processo de inicialização tarde o suficiente para que ele não seja mais seguido por nenhum outro processo.
Meu último palpite seria alterar o destino padrão do systemd de gráfico para um novo (sleepydisks), que depende do antigo destino gráfico.
Mas não existe uma maneira mais fácil e simples de desligar os discos?
Cumprimentos
Responder1
Abra o utilitário de discos e configure a unidade para desligar automaticamente após 10 minutos de inatividade.
Responder2
Use a opção -S do hdparm. Isso define o tempo limite de rotação, que deve ser mantido pela unidade.
$ hdparm --help
-S Set standby (spindown) timeout
$ hdparm -S 60 /dev/sdd
/dev/sdd:
setting standby to 60 (5 minutes)
Observe que este é um 'S' maiúsculo.
Responder3
Eu uso o script a seguir para "forçar" a rotação dos discos ociosos, onde por força quero dizer uma instrução direta para a unidade, já que muitas unidades WD são problemáticas com a rotação automática. Talvez você possa estender isso às suas necessidades. O script está bem comentado, então você poderá modificá-lo facilmente. Eu ligo a cron
cada 20 minutos, ajuste conforme necessário:
spindown.sh
#!/usr/bin/env bash
logger "[SPINDOWN] Checking disk activity and spinning down idles..."
# Exit during maintenance
if pgrep snapraid > /dev/null; then
logger "[SPINDOWN] Detected snapRAID maintenance. Exiting.";
exit 0
fi
# Specify any drives you want to ignore; separate multiple drives by spaces; e.g. "sda sdb"
IGNORE_DRIVES=""
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
# Check for idle disks and spin them down unless smartd is running tests
# Create a file on the ramdisk and cycle it to test for disk activity
( if [ ! -f /dev/shm/diskstats_1 ]; then
logger "[SPINDOWN] Creating initial state file on ramdisk";
touch /dev/shm/diskstats_1;
fi ;
logger "[SPINDOWN] Updating state files on ramdisk";
mv /dev/shm/diskstats_1 /dev/shm/diskstats_2;
cat /proc/diskstats > /dev/shm/diskstats_1 ) > /dev/null 2>&1
# Find all removable USB drives, so we can ignore them later,
# see http://superuser.com/a/465953
REMOVABLE_DRIVES=""
for _device in /sys/block/*/device; do
if echo $(readlink -f "$_device")|egrep -q "usb"; then
_disk=$(echo "$_device" | cut -f4 -d/)
REMOVABLE_DRIVES="$REMOVABLE_DRIVES $_disk"
fi
done
# Append detected removable drives to manually ignored drives
IGNORE_DRIVES="$IGNORE_DRIVES $REMOVABLE_DRIVES"
# Loop through all the array disks and spin down the idle disks. Will find all drives sda > sdz AND sdaa > sdaz...
logger "[SPINDOWN] Looping through drives to detect idle state"
for disk in `find /dev/ -regex '/dev/sd[a-z]+' | cut -d/ -f3`
do
# Skip removable USB drives and those the user wants to ignore
if [[ $IGNORE_DRIVES =~ $disk ]]; then
continue
fi
# Skip SSDs
if [[ $(cat /sys/block/$disk/queue/rotational) -eq 0 ]]; then
continue
fi
# Check if drive exists
if [ -e /dev/$disk ]; then
logger "[SPINDOWN] Checking drive $disk"
# Check if drive is currently spinning
if [ "$(smartctl -i -n standby /dev/$disk | grep "ACTIVE or IDLE")" ]; then
logger "[SPINDOWN] Disk $disk is ACTIVE or IDLE. Checking for selftest"
# Check if smartctl is currently not running a self test
if [ $(smartctl -a /dev/$disk | grep -c "Self-test routine in progress") = 0 ]; then
logger "[SPINDOWN] Disk $disk is not running a self test. Checking activity."
# Check if drive has been non idle since last run
if [ "$(diff /dev/shm/diskstats_1 /dev/shm/diskstats_2 | grep $disk )" = "" ]; then
logger "[SPINDOWN] Spinning down /dev/$disk `df -h | grep /dev/$disk | rev | cut -d ' ' -f 1 | rev`"
hdparm -y /dev/$disk
fi
else
logger "[SPINDOWN] /dev/$disk is running Self-test routine. Skipping."
fi
fi
fi
done
De acordo com a pergunta específica, como fazer isso com o systemd? ... crie um arquivo de timer que chame este script (Ref:https://wiki.archlinux.org/index.php/Systemd/Timers)