Power management

From ArchWiki
Revision as of 11:04, 13 April 2019 by Apollo22 (talk | contribs) (Power saving: Refactoring)
Jump to navigation Jump to search

Power management is a feature that turns off the power or switches system's components to a low-power state when inactive.

In Arch Linux, power management consists of two main parts:

  1. Configuration of the Linux kernel, which interacts with the hardware.
  2. 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.

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 similarly. Have a look at the power management category to get an overview on what power management options exist in Arch Linux.

These are the more popular scripts and tools designed to help power saving:

Console

  • acpid — A daemon for delivering ACPI power management events with netlink support.
http://sourceforge.net/projects/acpid2/ || acpid
  • 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.
https://github.com/rickysarraf/laptop-mode-tools || laptop-mode-toolsAUR
  • powertop — A tool to diagnose issues with power consumption and power management to help set power saving settings.
https://01.org/powertop/ || powertop
  • systemd — A system and service manager.
https://freedesktop.org/wiki/Software/systemd/ || systemd
  • TLP — Advanced power management for Linux.
http://linrunner.de/tlp || tlp

Graphical

  • batterymon-clone — Simple battery monitor tray icon.
https://github.com/jareksed/batterymon-clone || batterymon-cloneAUR
  • cbatticon — Lightweight and fast battery icon that sits in your system tray.
https://github.com/valr/cbatticon || cbatticon
  • GNOME Power Statistics — System power information and statistics for GNOME.
https://gitlab.gnome.org/GNOME/gnome-power-manager || gnome-power-manager
  • KDE Power Devil — Power management module for Plasma.
https://userbase.kde.org/Power_Devil || powerdevil powerdevil-lightAUR
  • LXQt Power Management — Power management module for LXQt.
https://github.com/lxqt/lxqt-powermanagement || lxqt-powermanagement
  • MATE Power Management — Power management tool for MATE.
https://github.com/mate-desktop/mate-power-manager || mate-power-manager
  • MATE Power Statistics — System power information and statistics for MATE.
https://github.com/mate-desktop/mate-power-manager || mate-power-manager
  • Xfce Power Manager — Power manager for Xfce.
https://docs.xfce.org/xfce/xfce4-power-manager/start || xfce4-power-manager
  • vattery — Battery monitoring application written in Vala that will display the status of a laptop battery in a system tray.
http://www.jezra.net/projects/vattery || vatteryAUR

Power management with systemd

ACPI events

systemd handles some power-related ACPI events, whose actions can be configured in /etc/systemd/logind.conf or /etc/systemd/logind.conf.d/*.conf — see logind.conf(5). On systems with no dedicated power manager, this may replace the acpid daemon which is usually used to react to these ACPI events.

The specified action for each event can be one of ignore, poweroff, reboot, halt, suspend, hibernate, hybrid-sleep, suspend-then-hibernate, lock or kexec. In case of hibernation and suspension, they must be properly set up. If an event is not configured, systemd will use a default action.

Event handler Description Default action
HandlePowerKey Triggered when the power key/button is pressed. poweroff
HandleSuspendKey Triggered when the suspend key/button is pressed. suspend
HandleHibernateKey Triggered when the hibernate key/button is pressed. hibernate
HandleLidSwitch Triggered when the lid is closed, except in the cases below. suspend
HandleLidSwitchDocked Triggered when the lid is closed if the system is inserted in a docking station, or more than one display is connected. ignore
HandleLidSwitchExternalPower Triggered when the lid is closed if the system is connected to external power. action set for HandleLidSwitch

To apply any changes, restart systemd-logind.service (be warned that this will terminate all login sessions that might still be open).

Note: systemd cannot handle AC and Battery ACPI events, so if you use Laptop Mode Tools or other similar tools acpid is still required.

Power managers

Some desktop environments include power managers which inhibit (temporarily turn off) some or all of the systemd ACPI settings. If such a power manager is running, then the actions for ACPI events can be configured in the power manager alone. Changes to /etc/systemd/logind.conf or /etc/systemd/logind.conf.d/*.conf need be made only if you wish to configure behaviour for a particular event that is not inhibited by the power manager.

Note that if the power manager does not inhibit systemd for the appropriate events you can end up with a situation where systemd suspends your system and then when the system is woken up the other power manager suspends it again. As of December 2016, the power managers of KDE, GNOME, Xfce and MATE issue the necessary inhibited commands. If the inhibited commands are not being issued, such as when using acpid or others to handle ACPI events, set the Handle options to ignore. See also systemd-inhibit(1).

xss-lock

xss-lock subscribes to the systemd-events suspend, hibernate, lock-session, and unlock-session with appropriate actions (run locker and wait for user to unlock or kill locker). xss-lock also reacts to DPMS events and runs or kills the locker in response.

Start xss-lock in your autostart, for example

xss-lock -- i3lock -n -i background_image.png &

Suspend and hibernate

systemd provides commands to suspend to RAM or hibernate 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.

There are also two modes combining suspend and hibernate:

  • systemctl hybrid-sleep suspends the system both to RAM and disk, so a complete power loss does not result in lost data. This mode is also called suspend to both.
  • systemctl suspend-then-hibernate initially suspends the system to RAM and if it is not interrupted within the delay specified by HibernateDelaySec in systemd-sleep.conf(5), then the system will be woken using an RTC alarm and hibernated.
Note: systemd can also use other suspend backends (such as Uswsusp), in addition to the default kernel backend, in order to put the computer to sleep or hibernate. See Uswsusp#With systemd for an example.

Hybrid-sleep on suspend or hibernation request

It is possible to configure systemd to always do a hybrid-sleep even on a suspend or hibernation request.

The default suspend and hibernation action can be configured in the /etc/systemd/sleep.conf file. To set both actions to hybrid-sleep:

/etc/systemd/sleep.conf
[Sleep]
# suspend=hybrid-sleep
SuspendMode=suspend
SuspendState=disk
# hibernate=hybrid-sleep
HibernateMode=suspend
HibernateState=disk

See the sleep.conf.d(5) manual page for details and the linux kernel documentation on power states.

Sleep hooks

Suspend/resume service files

Service files can be hooked into suspend.target, hibernate.target, sleep.target, hybrid-sleep.target and suspend-then-hibernate.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
ExecStart=/usr/bin/sflock
ExecStartPost=/usr/bin/sleep 1

[Install]
WantedBy=sleep.target
/etc/systemd/system/resume@.service
[Unit]
Description=User resume actions
After=suspend.target

[Service]
User=%I
Type=simple
ExecStart=/usr/local/bin/ssh-connect.sh

[Install]
WantedBy=suspend.target
Note: As screen lockers may return before the screen is "locked", the screen may flash on resuming from suspend. Adding a small delay via ExecStartPost=/usr/bin/sleep 1 helps prevent this.

For root/system actions (enable the root-resume and root-suspend services to have them started at boot):

/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
/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

A couple of handy hints about these service files (more in systemd.service(5)):

  • If Type=oneshot then you can use multiple ExecStart= lines. Otherwise only one ExecStart line is allowed. You can add more commands with either ExecStartPre 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 because sleep.target itself is a StopWhenUnneeded service, the hook is guaranteed to start/stop properly for different tasks.

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 or post, depending on whether the machine is going to sleep or waking up
  • Argument 2: suspend, hibernate or hybrid-sleep, depending on which is being invoked

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[broken link: invalid section]:

# journalctl -b -u systemd-suspend.service
Note: You can also use sleep.target, suspend.target, hibernate.target or hybrid-sleep.target to hook units into the sleep state logic instead of using custom scripts.

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 systemd.special(7) and systemd-sleep(8) 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 was made configurable with systemd v220:[2]

/etc/systemd/logind.conf
...
HoldoffTimeoutSec=30s
...

Suspend from corresponding laptop Fn key not working

If, regardless of the setting in logind.conf, the sleep button does not work (pressing it does not even produce a message in syslog), then logind is probably not watching the keyboard device. [3] Do:

# journalctl --grep="Watching system buttons"

You might see something like this:

May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event2 (Power Button)
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event3 (Sleep Button)
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event4 (Video Bus)

Notice no keyboard device. Now obtain ATTRS{name} for the parent keyboard device [4] :

# udevadm info -a /dev/input/by-path/*-kbd
...
KERNEL=="event0"
...
ATTRS{name}=="AT Translated Set 2 keyboard"

Now write a custom udev rule to add the "power-switch" tag:

/etc/udev/rules.d/70-power-switch-my.rules
ACTION=="remove", GOTO="power_switch_my_end"
SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="AT Translated Set 2 keyboard", TAG+="power-switch"
LABEL="power_switch_my_end"

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

Reason: Explicit systemctl commands should not be provided. (Discuss in Talk:Power management#)

Restart services and reload rules:

# systemctl restart systemd-udevd.service
# udevadm trigger
# systemctl restart systemd-logind.service

Now you should see Watching system buttons on /dev/input/event0 in syslog.

There are numerous utilities to lock the screen of a session. But it is important to note that the utility to use is highly dependant on the environment your are in, either the virtual console, or a specific display server (Xorg or Wayland).

See List of screen lockers.

By environment

Terminal

setterm --blank 1

virtual console

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: vlock? (Discuss in Talk:Power management#)

Xorg

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: please use the first argument of the template to provide a brief explanation. (Discuss in Talk:Power management#)

Wayland tools

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: please use the first argument of the template to provide a brief explanation. (Discuss in Talk:Power management#)

Triggering the lock

You can lock a session using different methods:

  • from a terminal
  • using a GUI:
 * from a desktop icon
 * using hot corners
 * from a menu (mouse or keyboard driven)
 * inactivity
 * another action (suspend, hibernate, ...)

The last point (triggering a lock from an event) is the trickiest, because you can do it one of two ways:

 * get the action trigger to execute your lock, then to execute the initial action.
 * from the event trigger, add the lock to the event chain. So far this can only be done using systemd.

List of triggers

Manual

Inactivity

You can trigger a lock on inactivity using systemd, DPMS (see xss-lock or xautolock

Suspend / Hibernate

See systemd

 Service file dependency
 Hook to xss-lock

Xorg triggers

xss-lock

xss-lock is triggered by one of two things:

The advantage of this is that you can control a lock issued manually, by inactivity, and by a suspend command at the same place.

To execute an action on one of those events:

xss-lock <locker-utility>

systemd events

By default, xss-lock subscribes to suspend, hibernate, lock-session, and unlock-session with appropriate actions (run locker and wait for user to unlock or kill locker).

You can prevent xss-lock from being triggered by suspend and hibernate using --ignore-sleep.

You can trigger a manual lock using loginctl lock-session.

DPMS

To configure DPMS signaling timeout:

  # Trigger screensaver after 10 minutes of inactivity
  xset s on
  xset s 600

DPMS signaling can also be configured in /etc/X11/xorg.conf.d/ in the Monitor section.

Using DPMS signaling, you can set a second timer, for exemple to notify the user or to dim the screen. For exemple (from xss-lock(5):

# Dim the screen after three minutes of inactivity, lock the screen two minutes later using i3lock:

xset 180 120
xss-lock -n dim-screen.sh -- i3lock -n
Note:

When using xss-lock with DPMS, you will have to blank the screen yourself. It won't be triggered when looking at videos

xautolock

xautolock -time 12 -locker "systemctl suspend" -detectsleep
Note:

xautolock has restrictive timer limits:

  • 1 min to 1 hour for time
  • 10 min to 2 hour for killtime

It might be necessary to add -detectsleep to prevent xautolock from locking the session after resuming. One nice feature of xautolock is the corners.

Wayland triggers

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: please use the first argument of the template to provide a brief explanation. (Discuss in Talk:Power management#)

SystemD triggers

DBUS Notification

Using loginctl lock-session, or the lock action in logind.conf(5), you can notify the system through DBUS that you want to lock. This notification can the be processed, for exemple by xss-lock.

Inactivity

In logind.con(5), you can configure the IdleAction to lock. This will trigger a DBUS notification, that will have to be processed (for exemple by xsslock) to lock the session.

Note that this is for a global system (so this is not ideal for a multi user environment).

Note also that "this requires that user sessions correctly report the idle status to the system".

Units

Before suspend/hibernate

You can use a Sleep hook.

[Unit]
Description=Lock the screen
Before=sleep.target
 
[Service]
#User=user
Environment=DISPLAY=:0
ExecStart=i3lock
 
[Install]
WantedBy=sleep.target

Lid closing

You can use the lock action using the related ACPI Event

Actions after the lock has been triggered

Suspend/Hibernate after X Shudown screen

See also

Tools and scripts

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

Reason: Merged from Power saving, needs reorganization to fit into this page. (Discuss in Talk:Power management#)

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"
Note: You can use the same script that pm-powersave uses. You just have to make it executable and place it somewhere else (for example /usr/local/bin/).

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!

Note: Be aware that AC0 may be different for your laptop, change it if that is the case.

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