mirror of
https://codeberg.org/privacy1st/nix-git
synced 2024-12-05 00:05:04 +01:00
123 lines
5.6 KiB
Nix
123 lines
5.6 KiB
Nix
# hdparm - get/set SATA/IDE device parameters
|
|
# -q Handle the next option quietly, suppressing normal output (but not error messages).
|
|
# -I Print device information.
|
|
# -C Check the current IDE power mode status:
|
|
# unknown (drive does not support this command)
|
|
# active/idle (normal operation)
|
|
# standby (low power mode, drive has spun down)
|
|
# sleeping (lowest power mode, drive is completely shut down)
|
|
# -S Set the standby (spindown) timeout for the drive.
|
|
# The timeout specifies how long to wait in idle (with no disk activity) before turning off the motor to save power.
|
|
# The value of 0 disables spindown,
|
|
# the values from 1 to 240 specify multiples of 5 seconds
|
|
# and values from 241 to 251 specify multiples of 30 minutes.
|
|
# -y Force an IDE drive to immediately enter the low power consumption standby mode, usually causing it to spin down.
|
|
|
|
# Get power status:
|
|
# sudo hdparm -C /dev/disk/by-id/ata-WDC_WD40EFRX-68N32N0_WD-WCC7K0CPF0N1
|
|
# #=> drive state is: active/idle
|
|
|
|
# Spin down after 2 minutes (120s/5s = 24).
|
|
# TODO: Western Digital (WD) Red/Green drives don't work properly. For low `-S` values, they spin down after **10** minutes. And for high values they don't spin down at all.
|
|
# - https://superuser.com/questions/1746074/spin-down-not-working-on-wd-red
|
|
# - https://askubuntu.com/questions/196473/setting-sata-hdd-spindown-time-for-western-digital-green-drives
|
|
#
|
|
# sudo hdparm -S 24 /dev/disk/by-id/ata-WDC_WD40EFRX-68N32N0_WD-WCC7K0CPF0N1 # 4tb1
|
|
# sudo hdparm -S 24 /dev/disk/by-id/ata-WDC_WD30EFRX-68EUZN0_WD-WCC4N1173157 # 3tb1
|
|
# sudo hdparm -S 24 /dev/disk/by-id/ata-WDC_WD30EFRX-68EUZN0_WD-WMC4N0564095 # 3tb2
|
|
#
|
|
# ... after > 10 minutes ...
|
|
#
|
|
# Query disk without waking it up:
|
|
# https://wiki.archlinux.org/title/hdparm#Querying_the_status_of_the_disk_without_waking_it_up
|
|
# sudo smartctl -i -n standby /dev/disk/by-id/ata-WDC_WD40EFRX-68N32N0_WD-WCC7K0CPF0N1
|
|
# #=> Device is in STANDBY mode, exit(2)
|
|
#
|
|
# Get power status:
|
|
# sudo hdparm -C /dev/disk/by-id/ata-WDC_WD40EFRX-68N32N0_WD-WCC7K0CPF0N1
|
|
# sudo hdparm -C /dev/disk/by-id/ata-WDC_WD30EFRX-68EUZN0_WD-WCC4N1173157
|
|
# sudo hdparm -C /dev/disk/by-id/ata-WDC_WD30EFRX-68EUZN0_WD-WMC4N0564095
|
|
# #=> drive state is: standby
|
|
|
|
# Power savings.
|
|
# With 12tb1, 3tb1, 3tb2 spinning and 4tb1 spun-down: 26.1 W
|
|
# With 12tb1 spinning and 3tb1, 3tb2, 4tb1 spun-down: 19.8 W
|
|
# -> WD30EFRX measured idle spinning vs standby = +3.15 W
|
|
# -> WD30EFRX advertised idle spinning vs unplugged = +3.0 W
|
|
|
|
# See also: Systemd service to spin down after boot. https://wiki.archlinux.org/title/hdparm#Putting_a_drive_to_sleep_directly_after_boot
|
|
|
|
# If a (external) disk does not supprot setting a timer with hdparm, use `hd-idle` instead.
|
|
# https://www.reddit.com/r/NixOS/comments/751i5t/comment/do3f3l7/
|
|
# # Options:
|
|
# # -a <disk path without /dev>: Select disk for subsequent parameters.
|
|
# # -i 120: Spin down after 2 minutes (120 seconds) of inactivity.
|
|
# ExecStart = "${pkgs.hd-idle}/bin/hd-idle -a disk/by-id/XXX-XXX-XXX -i 120";
|
|
|
|
# Example usage:
|
|
# sudo smartctl -i -n standby /dev/disk/by-id/ata-WDC_WD60EFAX-68SHWN0_WD-WX31D29924PZ | grep 'Power mode'
|
|
# #=> Power mode is: ACTIVE or IDLE
|
|
# sudo hd-idle -a disk/by-id/ata-WDC_WD60EFAX-68SHWN0_WD-WX31D29924PZ -i 120
|
|
|
|
{ lib, config, options, pkgs, modulesPath, ... }:
|
|
with lib;
|
|
let
|
|
cfg = config.yoda.spin-down.hdparm;
|
|
in
|
|
{
|
|
options = {
|
|
yoda.spin-down.hdparm = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [ ];
|
|
example = ["ata-WDC_WD40EFRX-68N32N0_WD-WCC7K0CPF0N1"];
|
|
description = ''
|
|
List with IDs (/dev/disk/by-id/<ID>) of HDDs to spin down with hdparm after 2-10 minutes.
|
|
|
|
Not all HDDs (e.g. Seagate Barracuda ST600DM003) and many external disk enclosures don't support setting the idle timer.
|
|
In that case, please use yoda.spin-down.hd-idle for those disks instead.
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = mkIf (length cfg > 0) {
|
|
# For each element (e.g. "ata-WDC_WD40EFRX-68N32N0_WD-WCC7K0CPF0N1") in `cfg` create this config:
|
|
# systemd.services."hdparm-ata-WDC_WD40EFRX-68N32N0_WD-WCC7K0CPF0N1" = {
|
|
# description = ...;
|
|
# wantedBy = ...;
|
|
# ...
|
|
# };
|
|
systemd.services = builtins.listToAttrs (builtins.map (id: {
|
|
name = "hdparm-${id}";
|
|
value = {
|
|
description = "Spin down inactive HDD ${id}";
|
|
wantedBy = [ "multi-user.target" ];
|
|
serviceConfig.Type = "oneshot";
|
|
script = ''
|
|
set -eu -o pipefail
|
|
# Get IDE power mode status and remove any whitespace characters for easier pattern matching.
|
|
result="$(${pkgs.hdparm}/bin/hdparm -C /dev/disk/by-id/${id} | ${pkgs.coreutils}/bin/tr -d '[:space:]')"
|
|
case "''${result}" in
|
|
*'/dev/disk/by-id/${id}:drivestateis:standby'*|*'/dev/disk/by-id/${id}:drivestateis:sleeping'*)
|
|
printf '%s\n' 'Disk is in standby or sleeping.'
|
|
# Don't set idle timeout as this would spin up the disk.
|
|
# It has already been set before, otherwise the disk would be spinning.
|
|
;;
|
|
*'/dev/disk/by-id/${id}:drivestateis:active/idle'*)
|
|
printf '%s\n' 'Disk is active. Set idle timeout to 10 minutes.'
|
|
${pkgs.hdparm}/bin/hdparm -S 24 /dev/disk/by-id/${id}
|
|
;;
|
|
*'/dev/disk/by-id/${id}:drivestateis:unknown'*)
|
|
printf '%s\n' 'Disk is not supported by hdparm.'
|
|
exit 1
|
|
;;
|
|
*)
|
|
printf '%s%s\n' 'Unknown hdparm output: ' "''${result}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
'';
|
|
};
|
|
}) cfg);
|
|
};
|
|
}
|