====== Espressobin: uspávání rotačního HDD pomocí hdparm ====== //Vytvořeno: **8.6.2020**// > **Poznámka k aktuálnosti:** Toto je dobový článek. Postup vychází z konkrétního nasazení na Espressobinu s Nextcloudem a nemusí odpovídat dnešnímu stavu systemd, NextcloudPi ani nástrojů kolem storage. > > **Důležité:** Tento článek se týká klasického rotačního HDD. Pro SSD a NVMe se podobné uspávání přes ''hdparm'' běžně nepoužívá. [[https://wiki.archlinux.org/index.php/hdparm|hdparm]] umožňuje nastavit standby režim rotačního disku. V mém případě šlo o HDD připojený k Espressobinu, kde jsem chtěl snížit hlučnost a zbytečné opotřebení mechaniky. Samotné nastavení ale komplikovalo několik souběžných problémů: Advanced Power Management, procesy probouzející disk a nepřesnosti při sledování ''/proc/diskstats''. ===== Základní nastavení přes hdparm ===== Uspání po 30 minutách idle času odpovídalo hodnotě ''-S 241'': hdparm -S 241 /dev/sda Okamžité uspání disku: hdparm -y /dev/sda Pro sledování stavu se hodilo průběžné ověřování: while : ; do /sbin/hdparm -C /dev/sda; sleep 1; done Nebo: watch -n 1 hdparm -C /dev/sda Později jsem zjistil důležitou věc: dotaz ''hdparm -C /dev/sda'' mění statistiky v ''/proc/diskstats'', takže může rušit vlastní logiku pro vyhodnocení nečinnosti disku. ===== Advanced Power Management ===== Na některých systémech stačilo použít jen ''-S''. Na Espressobinu se disk neuspával vůbec, takže jsem zkoušel i [[https://en.wikipedia.org/wiki/Advanced_Power_Management|Advanced Power Management]] přes parametr ''-B''. Například: hdparm -B 127 /dev/sda Nebo kombinaci: hdparm -B 50 -S 241 /dev/sda V praxi se ale uspávání chovalo nevyzpytatelně. Disk se někdy neuspal vůbec a jindy usínal dřív, než jsem čekal. Na této cestě jsem nakonec rezignoval. ===== Vlastní skript nad /proc/diskstats ===== Nakonec se mi osvědčilo nečekat, že se disk bude uspávat jen podle interní logiky ''hdparm'', ale pravidelně kontrolovat změny v ''/proc/diskstats'' a při nečinnosti ručně spustit ''hdparm -y''. Původní jednodušší verze skriptu: #!/bin/bash # Get new state from diskstats devcode=$(findfs UUID=hFAc5i-yMtV-UC83-jF99-UnqA-ck7f-qYlnzo | cut -c 6-8) NEWstate=$(cat /proc/diskstats | grep $devcode) echo $NEWstate > /run/diskNEWstate.txt # compare md5 sums md5new=$(md5sum /run/diskNEWstate.txt | sed 's/ .*//') md5old=$(md5sum /run/diskOLDstate.txt | sed 's/ .*//') # if no changes, power down if [ "$md5new" = "$md5old" ]; then hdparm -y /dev/disk/by-id/ata-ST4000VN008-2DR166_ZDH8BP5S echo "going to sleep" fi # Write current state to file echo $NEWstate > /run/diskOLDstate.txt Skript byl spouštěný přes [[https://cs.wikipedia.org/wiki/Cron|cron]] každých 30 minut. Když se obsah ''/proc/diskstats'' od minulého běhu nezměnil, disk se uspal. ===== Vylepšená verze skriptu ===== Později jsem zjistil, že i u uspaného disku se mění některé sloupce v ''/proc/diskstats''. Proto jsem skript rozšířil o odstranění sloupců, které nemělo smysl sledovat: #!/bin/bash # Get new state from diskstats devcode=$(findfs UUID=hFAc5i-yMtV-UC83-jF99-UnqA-ck7f-qYlnzo | cut -c 6-8) NEWstate=$(cat /proc/diskstats | grep $devcode) del_column () { NEWstate=$(echo $NEWstate | sed -r 's/(\s+)?\S+//'$1) } del_column 14 del_column 13 del_column 7 del_column 6 del_column 4 echo $NEWstate > /run/diskNEWstate.txt # compare md5 sums md5new=$(md5sum /run/diskNEWstate.txt | sed 's/ .*//') md5old=$(md5sum /run/diskOLDstate.txt | sed 's/ .*//') # if no changes, power down if [ "$md5new" = "$md5old" ]; then hdparm -y /dev/disk/by-id/ata-ST4000VN008-2DR166_ZDH8BP5S echo "going to sleep" else #if changes date >> /etc/scripts/sleep.log fi # Write current state to file echo $NEWstate > /run/diskOLDstate.txt ===== Automatické nastavení po restartu ===== Pokud se použije čistě ''hdparm'', je dobré pamatovat na to, že nastavení po restartu mizí. U systemd systému jsem to tehdy řešil přes vlastní službu: # /usr/lib/systemd/system/sda-spindown.service [Unit] Description=Set HDD spindown [Service] Type=oneshot ExecStart=/sbin/hdparm -B 241 /dev/sdb RemainAfterExit=yes [Install] WantedBy=multi-user.target Aktivace služby: systemctl daemon-reload systemctl enable sda-spindown.service systemctl start sda-spindown.service ===== Co disk probouzelo ===== Nejvíc času zabralo hledání procesů, které disk probouzely. V mém případě šlo hlavně o údržbu Nextcloudu a monitoring stavu disku v NextcloudPi. První krok bylo omezit frekvenci Nextcloud cronu. Místo každých 15 minut jsem ho nechal běžet jen jednou denně: crontab -e -u www-data 12 10 * * * php -f /var/www/nextcloud/cron.php Druhý problém byl v NextcloudPi: zapnutá volba automatického monitoringu zdraví HDD probouzela disk prakticky pořád. Tuto volbu jsem vypnul. {{hardware:jednodeskove-pocitace:espressobin:pasted:nextcloud-hdd-health-monitor.jpg}} ===== Zdroje ===== * [[https://wiki.archlinux.org/index.php/hdparm|hdparm – ArchWiki]] * [[https://en.wikipedia.org/wiki/Advanced_Power_Management|Advanced Power Management]] * [[https://cstan.io/?p=8766&lang=en|Short tip: configure hard drive standby with systemd]] * [[https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats|Linux procfs diskstats]] * [[https://stackoverflow.com/questions/15361632/delete-a-column-with-awk-or-sed/38145415|Delete a column with awk or sed]] * [[https://bbs.archlinux.org/viewtopic.php?id=216832|hdparm: HDDs spindown after 10 sec, ignoring hdparm -S setting]] * [[https://unix.stackexchange.com/questions/410264/hdd-idle-settings-using-hdparm-apm-suspend|HDD idle settings using hdparm (APM, Suspend)]]