#!/bin/bash # throttle - user discrection power management utility while (( "$#" )); do #Find the number of physical cores (for hyperthreading control) CORES="$(grep "^core id" /proc/cpuinfo | sort -u | wc -l)" case "$1" in full|performance|cut|powersave) case "${1}" in full|performance) HYPERTHREADS="1" GOVERNOR="performance" XPSTURBO="0" ENERGYPERF="0" BACKLIGHT="2" # Higher? LAPTOP="0" DIRTYWBC="500" NMIDOG="0" # Always off POLICY="max_performance" APM="255" AAM="254" CONTROL="on" AUTOSUSPEND="-1" POWERSAVE="0" CONTROLLER="N" WLPOWERSAVE="off" WOLA="g" WOLB="enabled" LEDBRIGHT="255" NVPM="1" ;; cut|powersave) HYPERTHREADS="0" GOVERNOR="powersave" XPSTURBO="1" ENERGYPERF="15" BACKLIGHT="0" LAPTOP="5" DIRTYWBC="1500" NMIDOG="0" POLICY="min_power" APM="1" AAM="128" CONTROL="auto" AUTOSUSPEND="1" POWERSAVE="1" CONTROLLER="Y" WLPOWERSAVE="on" WOLA="d" WOLB="disabled" LEDBRIGHT="0" NVPM="0" ;; esac # Hyperthreads for i in /sys/devices/system/cpu/cpu*/online; do \ [[ "$(printf "${i}" | tr -cd [:digit:])" -ge "${CORES}" ]] && \ printf "${HYPERTHREADS}" > "${i}" & done & # CPU Governor for i in /sys/bus/cpu/drivers/processor/cpu*/cpufreq/scaling_governor; do \ [[ "${HYPERTHREADS}" == "0" && \ "$(printf ${i} | tr -cd [:digit:])" -ge "${CORES}" ]] && \ continue ; [[ "$(cat ${i})" == "${GOVERNOR}" ]] || printf "${GOVERNOR}" > "${i}" & done & # Disable Intel P-State Turbo [[ -f /sys/devices/system/cpu/intel_pstate/no_turbo ]] && \ printf "${XPSTURBO}" > /sys/devices/system/cpu/intel_pstate/no_turbo & # ENERGY_PERF_BIAS [[ -n "$(command -v x86_energy_perf_policy)" ]] && \ x86_energy_perf_policy "${ENERGYPERF}" & # Backlight [[ -f /sys/class/backlight/acpi_video0 ]] && \ for i in /sys/class/backlight/acpi_video*/brightness; do \ printf "${BACKLIGHT}" > "${i}" & done & # Virtual Memory (Swap) [[ "$(sysctl -n vm.laptop_mode)" == "${LAPTOP}" ]] || \ printf "${LAPTOP}" > /proc/sys/vm/laptop_mode & [[ "$(sysctl -n vm.dirty_writeback_centisecs)" == "${DIRTYWBC}" ]] || \ printf "${DIRTYWBC}" > /proc/sys/vm/dirty_writeback_centisecs & [[ "$(sysctl -n vm.dirty_expire_centisecs)" == "${DIRTYWBC}" ]] || \ printf "${DIRTYWBC}" > /proc/sys/vm/dirty_expire_centisecs & # NMI watchdog [[ -f /proc/sys/kernel/watchdog ]] && \ printf "${NMIDOG}" > /proc/sys/kernel/watchdog & # SATA link power management for i in /sys/class/scsi_host/host*/link_power_management_policy; do [[ -f "${i}" ]] && \ printf "${POLICY}" > "${i}" & done & # Hard drives [[ -n "$(command -v hdparm)" ]] && \ hdparm -qB "${APM}" -qM "${AAM}" /dev/[hs]d[a-z] 2> /dev/null & # Runtime power management for devices (with exceptions for devices by VID:PID) # Timing the switch with hyperthread cores going up or down is tricky. for i in /sys/{class/*,bus/*/devices}/*/power/control; do \ [[ "${CONTROL}" == "auto" ]] && \ [[ -n "$(printf ${i} | grep msr[${CORES}-$((${CORES} * 2 - 1))])" || \ -n "$(printf ${i} | grep machinecheck[${CORES}-$((${CORES} * 2 - 1))])" || \ -n "$(ls $(printf ${i} | sed 's|power.*||g')/*/ | grep 046D\:C52B)" || \ -n "$(ls $(printf ${i} | sed 's|power.*||g')/*/ | grep 054C\:0268)" || \ -f "$(printf ${i} | sed 's|/power.*|/idVendor|g')" && \ "$(cat $(printf ${i} | sed 's|/power.*|/idVendor|g'))" == "0424" && \ "$(cat $(printf ${i} | sed 's|/power.*|/idProduct|g'))" == "a700" ]] && \ continue || [[ "$(cat ${i})" == "${CONTROL}" ]] || printf "${CONTROL}" > "${i}" & done & # USB Autosuspend (with exceptions for devices by VID:PID) for i in /sys/bus/usb/devices/*/power/autosuspend{,_delay_ms}; do \ [[ "${AUTOSUSPEND}" == "1" ]] && \ [[ -n "$(ls $(printf ${i} | sed 's|power.*||g')/*/ | grep 046D\:C52B)" || \ -n "$(ls $(printf ${i} | sed 's|power.*||g')/*/ | grep 054C\:0268)" || \ -f "$(printf ${i} | sed 's|/power.*|/idVendor|g')" && \ "$(cat $(printf ${i} | sed 's|/power.*|/idVendor|g'))" == "0424" && \ "$(cat $(printf ${i} | sed 's|/power.*|/idProduct|g'))" == "a700" ]] && \ continue ; [[ "$(cat ${i})" == "${AUTOSUSPEND}" ]] || printf -- "${AUTOSUSPEND}" > "${i}" & done & # Powersaving for modules for i in /sys/module/*/parameters/power_save; do \ [[ "$(cat ${i})" == "${POWERSAVE}" ]] || printf "${POWERSAVE}" > "${i}" & done & for i in /sys/module/*/parameters/power_save_controller; do \ [[ "$(cat ${i})" == "${CONTROLLER}" ]] || printf "${CONTROLLER}" > "${i}" & done & # Network powersaving for i in /sys/class/net/wl*; do \ [[ -n "$(command -v iw)" ]] && \ iw dev "$(printf ${i} | sed 's/^.*wl/wl/')" set power_save "${WLPOWERSAVE}" 2> /dev/null & done & for i in /sys/class/net/e*; do \ [[ -n "$(command -v ethtool)" ]] && \ ethtool -s "$(printf ${i} | sed 's/^.*e/e/')" wol "${WOLA}" 2> /dev/null & done & for i in /sys/class/net/*/device/power/wakeup; do \ printf "${WOLB}" > "${i}" & done & # LEDs for i in /sys/class/leds/*/brightness; do \ printf "${LEDBRIGHT}" > "${i}" & done & # Nvidia PowerMizer [[ -n "$(command -v nvidia-settings)" ]] && \ DISPLAY=":0.0" nvidia-settings -a [gpu:0]/GPUPowerMizerMode="${NVPM}" > /dev/null & shift unset GOVERNOR XPSTURBO HYPERTHREADS ENERGYPERF BACKLIGHT LAPTOP DIRTYWBC NMIDOG \ POLICY APM AAM CONTROL AUTOSUSPEND POWERSAVE CONTROLLER \ WLPOWERSAVE WOLA WOLB LEDBRIGHT NVPM ;; ht*) case "${1}" in \ ht-on) HYPERTHREADS="1" ;; \ ht-off) HYPERTHREADS="0" ;; esac [[ -z "${HYPERTHREADS}" ]] && \ case "${2}" in \ on|performance) HYPERTHREADS="1"; SHIFT="2" ;; \ off|powersave) HYPERTHREADS="0"; SHIFT="2" ;; esac [[ -z "${HYPERTHREADS}" ]] && \ printf "${0} ht {on,off} - Hyperthreads\n" || \ for i in /sys/devices/system/cpu/cpu*/online; do [[ "$(printf "${i}" | tr -cd [:digit:])" -ge "${CORES}" ]] && \ printf "${HYPERTHREADS}" > "${i}" & done & [[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift unset HYPERTHREADS SHIFT ;; gov*) case "${1}" in \ gov-full) GOVERNOR="performance" ;; \ gov-cut) GOVERNOR="powersave" ;; esac [[ -z "${GOVERNOR}" ]] && \ case "${2}" in \ full|performance) GOVERNOR="performance"; SHIFT="2" ;; \ cut|powersave) GOVERNOR="powersave"; SHIFT="2" ;; esac [[ -z "${GOVERNOR}" ]] && \ printf "${0} gov {cut,full} - CPU Governor\n" || \ for i in /sys/bus/cpu/drivers/processor/cpu*/cpufreq/scaling_governor; do \ printf "${GOVERNOR}" > "${i}" & done & [[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift unset GOVERNOR SHIFT ;; turbo*) case "${1}" in \ turbo-on) XPSTURBO="0" ;; \ turbo-off) XPSTURBO="1" ;; esac [[ -z "${XPSTURBO}" ]] && \ case "${2}" in \ on|performance) XPSTURBO="0"; SHIFT="2" ;; \ off|powersave) XPSTURBO="1"; SHIFT="2" ;; esac [[ -z "${XPSTURBO}" ]] && \ printf "${0} turbo {on,off} - Intel P-State Turbo\n" || \ [[ -f /sys/devices/system/cpu/intel_pstate/no_turbo ]] && \ printf "${XPSTURBO}" > /sys/devices/system/cpu/intel_pstate/no_turbo & [[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift unset XPSTURBO SHIFT ;; backlight) case "${2}" in \ 0|powersave) BACKLIGHT="0"; SHIFT="2" ;; \ 1) BACKLIGHT="1"; SHIFT="2" ;; \ 2|performance) BACKLIGHT="2"; SHIFT="2" ;; esac [[ -z "${BACKLIGHT}" ]] && \ printf "${0} backlight {0,1,2} - Backlight brightness\n" || \ for i in /sys/class/backlight/acpi_video*/brightness; do \ printf "${BACKLIGHT}" > "${i}" & done & [[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift unset BACKLIGHT SHIFT ;; gpu*) case "${1}" in \ gpu-full) NVPM="1" ;; \ gpu-cut) NVPM="0" ;; esac [[ -z "${NVPM}" ]] && \ case "${2}" in \ full|performance) NVPM="1"; SHIFT="2" ;; \ cut|powersave) NVPM="0"; SHIFT="2" ;; esac [[ -z "${NVPM}" ]] && \ printf "${0} gpu {cut,full} - GPU runtime powersaving (only Nvidia ATM)\n" || \ [[ -z "$(command -v nvidia-settings)" ]] && \ printf "nvidia-settings not found; only nvidia currently supported" || \ DISPLAY=":0.0" nvidia-settings -a [gpu:0]/GPUPowerMizerMode="${NVPM}" > /dev/null & [[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift unset NVPM SHIFT ;; check) printf "\nHyperthreads\n/sys/devices/system/cpu/cpu*/online\n" for i in /sys/devices/system/cpu/cpu*/online; do \ [[ $(printf "${i}" | tr -cd [:digit:]) -ge "$CORES" ]] && \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/devices/system/cpu/||g; s|/.*||g; N;s|\n|\t|' printf "\nCPU Governor\n/sys/bus/cpu/drivers/processor/cpu*/cpufreq/scaling_governor\n" for i in /sys/bus/cpu/drivers/processor/cpu*/cpufreq/scaling_governor; do \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/bus/cpu/drivers/processor/||g; s|/.*||g; N;s|\n|\t|' [[ -f /sys/devices/system/cpu/intel_pstate/no_turbo ]] && \ echo -e "\nDisable Intel P-State Turbo\n/sys/devices/system/cpu/intel_pstate/\n"\ "no_turbo\t$(cat /sys/devices/system/cpu/intel_pstate/no_turbo)" [[ -n "$(command -v x86_energy_perf_policy)" ]] && \ printf "\nEnergy Perf Bias\n" && \ x86_energy_perf_policy -r #SUID printf "\nBacklight\n/sys/class/backlight/\n" for i in /sys/class/backlight/acpi_video*/brightness; do \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/backlight/||g; s|/.*||g; N;s|\n|\t|' echo -e "\nVirtual Memory (Swap)\n/proc/sys/vm/\n"\ "laptop_mode\t\t\t$(cat /proc/sys/vm/laptop_mode)\n"\ "dirty_writeback_centisecs\t$(cat /proc/sys/vm/dirty_writeback_centisecs)\n"\ "dirty_expire_centisecs\t\t$(cat /proc/sys/vm/dirty_expire_centisecs)" [[ -f /proc/sys/kernel/watchdog ]] && \ echo -e "\nNMI watchdog\n"\ "/proc/sys/kernel/watchdog\t$(cat /proc/sys/kernel/watchdog)" printf "\nSATA link power management\n/sys/class/scsi_host/host*/link_power_management_policy\n" for i in /sys/class/scsi_host/host*/link_power_management_policy; do \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/scsi_host/||g; s|/.*||g; N;s|\n|\t|' [[ -n "$(command -v hdparm)" ]] && \ printf "\nHard drives\n/dev/[hs]d[a-z]\n" && \ hdparm -B -M /dev/[hs]d[a-z] 2> /dev/null | sed 'N;s|\n||g; s|/dev/||g; s|\t| |g;' #SUID printf "\nRuntime power management\n/sys/{class,bus}/*/{*,devices/*}/power/control\n" for i in /sys/{class,bus}/*/{*,devices/*}/power/control; do \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/||g; s|/sys/bus/||g; s|/devices||g; s|/power/control||g; N;s|\n|\t|' printf "\nUSB Autosuspend\n/sys/bus/usb/devices/*/power/autosuspend{,_delay_ms}\n" for i in /sys/bus/usb/devices/*/power/autosuspend{,_delay_ms}; do \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/bus/usb/devices/||g; s|/.*||g; N;s|\n|\t|' printf "\nPower saving for modules\n/sys/module/*/parameters/power_save{,_controller}\n" for i in /sys/module/*/parameters/power_save{,_controller}; do \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/module/||g; s|/parameters/.*||g; s|/.*||g; N;s|\n|\t|' printf "\nNetwork device powersaving\n/sys/class/net/{wl*,e*,*/device/power/wakeup}\n"; [[ -n "$(command -v iw)" ]] && \ for i in /sys/class/net/wl*; do \ printf " ${i}\n$(iw dev $(printf ${i} | sed 's/^.*wl/wl/') get power_save)"; done | sed 's|^\t| |g;s|/sys/class/net/||g; s|/.*||g' [[ -n "$(command -v ethtool)" ]] && \ for i in /sys/class/net/e*; do \ printf " ${i}\n$(ethtool $(printf ${i} | sed 's/^.*e/e/') | grep Wake-on)"; done | sed 's|^\t| |g;s|/sys/class/net/||g; s|/.*||g' for i in /sys/class/net/*/device/power/wakeup; do \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/net/||g; s|/device/power/wakeup||g; s|/.*||g; N;s|\n|\t|' printf "\nLEDs\n/sys/class/leds/*/brightness\n" for i in /sys/class/leds/*/brightness; do \ printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/leds/||g; s|/brightness||g; s|/.*||g; N;s|\n|\t|' [[ -n "$(command -v nvidia-settings)" ]] && \ printf "\nNvidia PowerMizer\n " && \ DISPLAY=":0.0" nvidia-settings -q [gpu:0]/GPUPowerMizerMode | grep "Attribute" | sed 's|.*\[||g;s|\]):||g;s| |\t|g;s|\.$||g' shift ;; *|help) [[ ! "${1}" == "help" ]] && \ printf "Invalid input: ${@}\n" echo -e "\nRuntime power management:\n"\ "${0} {cut,full} - system-wide runtime powersaving\n"\ "${0} check - inspect runtime powersaving\n"\ "\nExtras:\n" \ "${0} gov {cut,full} - CPU Governor\n"\ "${0} turbo {on,off} - Intel P-State Turbo\n"\ "${0} ht {on,off} - Hyperthreads\n"\ "${0} backlight {0,1,2} -backlight brightness\n" \ "${0} gpu {cut,full} - GPU runtime powersaving (only Nvidia ATM)\n"\ "\nOptions can take {performace,powersave} and are stackable:\n"\ "\n${0} powersave gov full turbo on gpu full ht on check" exit ;; esac [[ -z "${1}" ]] || wait # Hey, let's stop! :) *stops* ... YAY! =D done