Power management
Related articles
The purpose of this page is to provide general overview of power management in Arch Linux. Power management consists of two main parts:
- Configuration of the Linux kernel, which interacts with hardware.
- Configuration of userspace tools, which interact with the kernel and react to its events. Many userspace tools also allow to modify kernel configuration in a "user-friendly" way. See #Userspace tools for the options.
Contents
Userspace tools
Using these tools can replace setting a lot of settings by hand. Only run one of these tools to avoid possible conflicts as they all work more or less similar. Have a look at the power management category to get an overview on what power management options exist in Archlinux.
These are the more popular scripts and tools designed to help power saving:
- aclidswitch — Simple Power Management tool to define custom lid, brightness and low battery actions depending on the laptop's AC state.
- acpid — A daemon for delivering ACPI power management events with netlink support.
- Laptop Mode Tools — Utility to configure laptop power saving settings, considered by many to be the de facto utility for power saving though may take a bit of configuration.
- pm-utils — Suspend and powerstate setting framework (largely undeveloped now).
- powertop — A tool to diagnose issues with power consumption and power management to help set power saving settings.
Power management with systemd
ACPI events
systemd handles some power-related ACPI events. These are configured in /etc/systemd/logind.conf
or /etc/systemd/logind.conf.d/*.conf
, and described in man logind.conf
.
The specified action can be one of ignore
, poweroff
, reboot
, halt
, suspend
, hibernate
, hybrid-sleep
, lock
or kexec
. If these options are not configured, systemd will use its defaults: HandlePowerKey=poweroff
, HandleSuspendKey=suspend
, HandleHibernateKey=hibernate
, and HandleLidSwitch=suspend
.
On systems with no dedicated power manager, this may replace the acpid daemon which is usually used to react to these ACPI events.
Handle*
options will apply unless inhibited (temporarily turned off) by a program, such as a power manager inside a desktop environment. If these inhibits are not taken, you can end up with a situation where systemd suspends your system, then when it wakes up the other power manager suspends it again. See also man systemd-inhibit
.
Suspend and hibernate
systemd provides commands for suspend to RAM, hibernate and a hybrid suspend using the kernel's native suspend/resume functionality. There are also mechanisms to add hooks to customize pre- and post-suspend actions.
systemctl suspend
should work out of the box, for systemctl hibernate
to work on your system you need to follow the instructions at Suspend and hibernate#Hibernation.
Hybrid sleep
systemctl hybrid-sleep
both hibernates and suspends at the same time. This combines some of the benefits and drawbacks of suspension and hibernation. This is useful in case a computer were to suddenly lose power (AC disconnection or battery depletion) since upon powerup it will resume from hibernation. If there is no power loss, then it will resume from suspension, which is much faster than resuming from hibernation. However, since "hybrid-sleep" has to dump memory to swap in order for hibernation to work, it is slower to enter sleep than a plain systemctl suspend
. An alternative is a delayed hibernation service file.
Sleep hooks
systemd does not use pm-utils to put the machine to sleep when using systemctl suspend
, systemctl hibernate
or systemctl hybrid-sleep
; pm-utils hooks, including any custom hooks, will not be run. However, systemd provides two similar mechanisms to run custom scripts on these events.
Suspend/resume service files
Service files can be hooked into suspend.target, hibernate.target and sleep.target to execute actions before or after suspend/hibernate. Separate files should be created for user actions and root/system actions. Enable the suspend@user
and resume@user
services to have them started at boot. Examples:
/etc/systemd/system/suspend@.service
[Unit] Description=User suspend actions Before=sleep.target [Service] User=%I Type=forking Environment=DISPLAY=:0 ExecStartPre= -/usr/bin/pkill -u %u unison ; /usr/local/bin/music.sh stop ; /usr/bin/mysql -e 'slave stop' ExecStart=/usr/bin/sflock [Install] WantedBy=sleep.target
/etc/systemd/system/resume@.service
[Unit] Description=User resume actions After=suspend.target [Service] User=%I Type=simple ExecStartPre=/usr/local/bin/ssh-connect.sh ExecStart=/usr/bin/mysql -e 'slave start' [Install] WantedBy=suspend.target
For root/system actions (enable the root-resume
and root-suspend
services to have them started at boot):
/etc/systemd/system/root-resume.service
[Unit] Description=Local system resume actions After=suspend.target [Service] Type=simple ExecStart=/usr/bin/systemctl restart mnt-media.automount [Install] WantedBy=suspend.target
/etc/systemd/system/root-suspend.service
[Unit] Description=Local system suspend actions Before=sleep.target [Service] Type=simple ExecStart=-/usr/bin/pkill sshfs [Install] WantedBy=sleep.target
A couple of handy hints about these service files (more in man systemd.service
):
- If
Type=oneshot
then you can use multipleExecStart=
lines. Otherwise only oneExecStart
line is allowed. You can add more commands with eitherExecStartPre
or by separating commands with a semicolon (see the first example above; note the spaces before and after the semicolon, as they are required). - A command prefixed with
-
will cause a non-zero exit status to be ignored and treated as a successful command. - The best place to find errors when troubleshooting these service files is of course with journalctl.
Combined Suspend/resume service file
With the combined suspend/resume service file, a single hook does all the work for different phases (sleep/resume) and for different targets (suspend/hibernate/hybrid-sleep).
Example and explanation:
/etc/systemd/system/wicd-sleep.service
[Unit] Description=Wicd sleep hook Before=sleep.target StopWhenUnneeded=yes [Service] Type=oneshot RemainAfterExit=yes ExecStart=-/usr/share/wicd/daemon/suspend.py ExecStop=-/usr/share/wicd/daemon/autoconnect.py [Install] WantedBy=sleep.target
-
RemainAfterExit=yes
: After started, the service is considered active until it is explicitly stopped. -
StopWhenUnneeded=yes
: When active, the service will be stopped if no other active service requires it. In this specific example, it will be stopped after sleep.target is stopped. - Because sleep.target is pulled in by suspend.target, hibernate.target and hybrid-sleep.target and sleep.target itself is a StopWhenUnneeded service, the hook is guaranteed to start/stop properly for different tasks.
Delayed hibernation service file
An alternative approach is delayed hibernation. This makes use of sleep hooks to suspend as usual but sets a timer to wake up later to perform hibernation. Here, entering sleep is faster than systemctl hybrid-sleep
since no hibernation is performed initially. However, unlike "hybrid-sleep", at this point there is no protection against power loss via hibernation while in suspension. This caveat makes this approach more suitable for laptops than desktops. Since hibernation is delayed, the laptop battery is only used during suspension and to trigger the eventual hibernation. This uses less power over the long-term than a "hybrid-sleep" which will remain suspended until the battery is drained. Note that if your laptop has a spinning hard disk, when it wakes up from suspend in order to hibernate, you may not want to be moving or carrying the laptop for these few seconds. Delayed hibernation may be desirable both to reduce power use as well as for security reasons (e.g. when using full disk encryption). An example script is located here. See also this post for an updated systemd sleep hook.
A slightly updated version of the service is:
/etc/systemd/system/suspend-to-hibernate.service
[Unit] Description=Delayed hibernation trigger Documentation=https://bbs.archlinux.org/viewtopic.php?pid=1420279#p1420279 Documentation=https://wiki.archlinux.org/index.php/Power_management Before=suspend.target Conflicts=hibernate.target hybrid-suspend.target StopWhenUnneeded=true [Service] Type=oneshot RemainAfterExit=yes Environment="WAKEALARM=/sys/class/rtc/rtc0/wakealarm" Environment="SLEEPLENGTH=+2hour" ExecStart=-/usr/bin/sh -c 'echo -n "alarm set for "; date +%%s -d$SLEEPLENGTH | tee $WAKEALARM' ExecStop=-/usr/bin/sh -c '\ alarm=$(cat $WAKEALARM); \ now=$(date +%%s); \ if [ -z "$alarm" ] || [ "$now" -ge "$alarm" ]; then \ echo "hibernate triggered"; \ systemctl hibernate; \ else \ echo "normal wakeup"; \ fi; \ echo 0 > $WAKEALARM; \ ' [Install] WantedBy=sleep.target
The Before
and Conflicts
options ensure it only is run for suspension and not hibernation--otherwise the service will run twice if delayed hibernation is triggered. The WantedBy
and StopWhenUnneeded
options are so it is started before sleep and stops upon resume. (Note that the suspend.target
and hibernate.target
targets do not stop when unneeded, but sleep.target
does). Enable the service.
Hooks in /usr/lib/systemd/system-sleep
systemd runs all executables in /usr/lib/systemd/system-sleep/
, passing two arguments to each of them:
- Argument 1: either
pre
orpost
, depending on whether the machine is going to sleep or waking up - Argument 2:
suspend
,hibernate
orhybrid-sleep
, depending on which is being invoked
In contrast to pm-utils, systemd will run these scripts concurrently and not one after another.
The output of any custom script will be logged by systemd-suspend.service, systemd-hibernate.service or systemd-hybrid-sleep.service. You can see its output in systemd's journal:
# journalctl -b -u systemd-suspend
An example of a custom sleep script:
/usr/lib/systemd/system-sleep/example.sh
#!/bin/sh case $1/$2 in pre/*) echo "Going to $2..." ;; post/*) echo "Waking up from $2..." ;; esac
Do not forget to make your script executable:
# chmod a+x /usr/lib/systemd/system-sleep/example.sh
See man 7 systemd.special
and man 8 systemd-sleep
for more details.
Troubleshooting
Delayed lid switch action
When performing lid switches in short succession, logind will delay the suspend action for up to 90s to detect possible docks. [1] This delay will be configurable with systemd v220. [2]
Power saving
This section is a reference for creating custom scripts and power saving settings such as by udev rules. Make sure that the settings are not managed by some other utility to avoid conflicts.
Almost all of the features listed here are worth using whether or not the computer is on AC or battery power. Most have negligible performance impact and are just not enabled by default because of commonly broken hardware/drivers. Reducing power usage means reducing heat, which can even lead to higher performance on a modern Intel or AMD CPU, thanks to dynamic overclocking.
Audio
By default, audio power saving is turned off by most drivers. It can be enabled by setting the power_save
parameter; a time (in seconds) to go into idle mode. To idle the audio card after one second, create the following file for Intel soundcards.
/etc/modprobe.d/audio_powersave.conf
options snd_hda_intel power_save=1
Alternatively, use the following for ac97:
options snd_ac97_codec power_save=1
Backlight
See Backlight.
Bluetooth
To disable bluetooth completely, blacklist the btusb
and bluetooth
modules.
To turn off bluetooth only temporarily, use rfkill:
# rfkill block bluetooth
Or with udev rule:
/etc/udev/rules.d/50-bluetooth.rules
# disable bluetooth SUBSYSTEM=="rfkill", ATTR{type}=="bluetooth", ATTR{state}="0"
Or just enable the instantiated rfkill-block@bluetooth.service
provided by the rfkill package.
Web camera
If you will not use integrated web camera then blacklist the uvcvideo
module.
Kernel parameters
This section uses configs in /etc/sysctl.d/
, which is "a drop-in directory for kernel sysctl parameters." See The New Configuration Files and more specifically systemd's sysctl.d man page for more information.
Disabling NMI watchdog
The NMI watchdog is a debugging feature to catch hardware hangs that cause a kernel panic. On some systems it can generate a lot of interrupts, causing a noticeable increase in power usage:
/etc/sysctl.d/disable_watchdog.conf
kernel.nmi_watchdog = 0
or add nmi_watchdog=0
to the kernel line to disable it completely from early boot.
Writeback Time
Increasing the virtual memory dirty writeback time helps to aggregate disk I/O together, thus reducing spanned disk writes, and increasing power saving. To set the value to 60 seconds (default is 5 seconds):
/etc/sysctl.d/dirty.conf
vm.dirty_writeback_centisecs = 6000
To do the same for journal commits on supported filesystems (e.g. ext4, btrfs...), use commit=60
as a option in fstab.
See also sysctl#Virtual memory for other parameters affecting I/O performance and power saving.
Laptop Mode
See the kernel documentation on the laptop mode 'knob.' "A sensible value for the knob is 5 seconds."
/etc/sysctl.d/laptop.conf
vm.laptop_mode = 5
Network interfaces
Wake-on-LAN can be a useful feature, but if you are not making use of it then it is simply draining extra power waiting for a magic packet while in suspend. Disabling for all Ethernet interfaces:
/etc/udev/rules.d/70-disable_wol.rules
ACTION=="add", SUBSYSTEM=="net", KERNEL=="eth*", RUN+="/usr/bin/ethtool -s %k wol d"
To enable powersaving on all wireless interfaces:
/etc/udev/rules.d/70-wifi-powersave.rules
ACTION=="add", SUBSYSTEM=="net", KERNEL=="wlan*", RUN+="/usr/bin/iw dev %k set power_save on"
In these examples, %k
is a specifier for the kernel name of the matched device. For example, if it finds that the rule is applicable to wlan0
, the %k
specifier will be replaced with wlan0
. To apply the rules to only a particular interface, just replace the pattern eth*
and specifier %k
with the desired interface name. For more information, see Writing udev rules.
In this case, the name of the configuration file is important. Due to the introduction of persistent device names via 80-net-name-slot.rules
in systemd v197, it is important that the network powersave rules are named lexicographically before 80-net-name-slot.rules
, so that they are applied before the devices are named e.g. enp2s0
.
Bus power management
Active State Power Management
If the computer is believed not to support ASPM it and will be disabled on boot:
$ lspci -vv | grep ASPM.*abled\;
ASPM is handled by the BIOS, if ASPM is disabled it will be because [ref]:
- The BIOS disabled it for some reason (for conflicts?).
- PCIE requires ASPM but L0s are optional (so L0s might be disabled and only L1 enabled).
- The BIOS might not have been programmed for it.
- The BIOS is buggy.
If believing the computer has support for ASPM it can be forced on for the kernel to handle with the pcie_aspm=force
kernel parameter.
To adjust to powersave
do (the following command will not work unless enabled):
echo powersave | tee /sys/module/pcie_aspm/parameters/policy
By default it looks like this:
$ cat /sys/module/pcie_aspm/parameters/policy
[default] performance powersave
PCI Runtime Power Management
/etc/udev/rules.d/pci_pm.rules
ACTION=="add", SUBSYSTEM=="pci", ATTR{power/control}="auto"
USB autosuspend
The linux kernel can automatically suspend USB devices when they are not in use. This can sometimes save quite a bit of power, however some USB devices are not compatible with USB power saving and start to misbehave (common for USB mice/keyboards). udev rules based on whitelist or blacklist filtering can help to mitigate the problem.
The most simple and likely useless example is enabling autosuspend for all USB devices:
/etc/udev/rules.d/50-usb_power_save.rules
ACTION=="add", SUBSYSTEM=="usb", TEST=="power/control", ATTR{power/control}="auto"
To allow autosuspend only for devices that are known to work, use simple matching against vendor and product IDs (use lsusb to get these values):
/etc/udev/rules.d/50-usb_power_save.rules
# whitelist for usb autosuspend ACTION=="add", SUBSYSTEM=="usb", TEST=="power/control", ATTR{idVendor}=="05c6", ATTR{idProduct}=="9205", ATTR{power/control}="auto"
Alternatively, to blacklist devices that are not working with USB autosuspend and enable it for all other devices:
/etc/udev/rules.d/50-usb_power_save.rules
# blacklist for usb autosuspend ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="05c6", ATTR{idProduct}=="9205", GOTO="power_usb_rules_end" ACTION=="add", SUBSYSTEM=="usb", TEST=="power/control", ATTR{power/control}="auto" LABEL="power_usb_rules_end"
The default autosuspend idle delay time is controlled by the autosuspend
parameter of the usbcore
kernel module. To set the delay to 5 seconds instead of the default 2 seconds:
/etc/modprobe.d/usb-autosuspend.conf
options usbcore autosuspend=5
Similarly to power/control
, the delay time can be fine-tuned per device by setting the power/autosuspend
attribute.
See the Linux kernel documentation for more information on USB power management.
SATA Active Link Power Management
/etc/udev/rules.d/hd_power_save.rules
ACTION=="add", SUBSYSTEM=="scsi_host", KERNEL=="host*", ATTR{link_power_management_policy}="min_power"
Hard disk drive
See hdparm#Power management configuration for drive parameters that can be set.
Power saving is not effective when too many programs are frequently writing to the disk. Tracking all programs, and how and when they write to disk is the way to limit disk usage. Use iotop to see which programs use the disk frequently. See Solid State Drives#Tips for minimizing disk reads/writes for other tips, most of them are not specific to SSDs.
Also little things like setting the noatime option can help. If enough RAM is available, consider disabling or limiting swappiness as it has the possibility to limit a good number of disk writes.
CD-ROM or DVD drive
See Udisks#udisks: Devices do not remain unmounted.
Tools and scripts
Using a script and an udev rule
Since systemd users can suspend and hibernate through systemctl suspend
or systemctl hibernate
and handle acpi events with /etc/systemd/logind.conf
, it might be interesting to remove pm-utils and acpid. There is just one thing systemd cannot do (as of systemd-204): power management depending on whether the system is running on AC or battery. To fill this gap, you can create a single udev rule that runs a script when the AC adapter is plugged and unplugged:
/etc/udev/rules.d/powersave.rules
SUBSYSTEM=="power_supply", ATTR{online}=="0", RUN+="/path/to/your/script true" SUBSYSTEM=="power_supply", ATTR{online}=="1", RUN+="/path/to/your/script false"
Examples of powersave scripts:
The above udev rule should work as expected, but if your power settings are not updated after a suspend or hibernate cycle, you should add a script in /usr/lib/systemd/system-sleep/
with the following contents:
/usr/lib/systemd/system-sleep/00powersave
#!/bin/sh case $1 in pre) /path/to/your/script false ;; post) if cat /sys/class/power_supply/AC0/online | grep 0 > /dev/null 2>&1 then /path/to/your/script true else /path/to/your/script false fi ;; esac exit 0
Do not forget to make it executable!
Now you do not need pm-utils anymore. Depending on your configuration, it may be a dependency of some other package. If you wish to remove it anyway, run pacman -Rdd pm-utils
.
Print power settings
This script prints power settings and a variety of other properties for USB and PCI devices. Note that root permissions are needed to see all settings.
#!/bin/bash for i in $(find /sys/devices -name "bMaxPower") do busdir=${i%/*} busnum=$(<$busdir/busnum) devnum=$(<$busdir/devnum) title=$(lsusb -s $busnum:$devnum) printf "\n\n+++ %s\n -%s\n" "$title" "$busdir" for ff in $(find $busdir/power -type f ! -empty 2>/dev/null) do v=$(cat $ff 2>/dev/null|tr -d "\n") [[ ${#v} -gt 0 ]] && echo -e " ${ff##*/}=$v"; v=; done | sort -g; done; printf "\n\n\n+++ %s\n" "Kernel Modules" for mod in $(lspci -k | sed -n '/in use:/s,^.*: ,,p' | sort -u) do echo "+ $mod"; systool -v -m $mod 2> /dev/null | sed -n "/Parameters:/,/^$/p"; done
See also
- Laptop#Power management describes power management specific for laptops - especially battery monitoring.
- General recommendations#Power management
- ThinkWiki:How to reduce power consumption
- Ubuntu Wiki's Power Saving Tweaks