Power management

From Alpine Linux

Power management is a feature of computer CPUs, GPUs and peripherals such as monitors and printers, that turns off the power or switches the system to a low-power state when inactive based on a standard called ACPI.

Installation

Alpine Linux comes inbuilt with a basic version of acpid as part of BusyBox.

A flexible and extensible acpid2 daemon with Netlink support for delivering ACPI events can be installed with the acpid package:

# apk add acpid

On installation of the above package, the inbuilt Busybox acpid daemon gets replaced.

Service configuration

Enable and start the acpid daemon using the standard OpenRC commands:

# rc-update add acpid && rc-service acpid start

Power management utilities

There are a number of power management utilities available in Alpine Linux. You may want to install one of them, if your Desktop software needs one.

Tool Website Brief Notes
zzz https://github.com/jirutka/zzz A simple program to suspend or hibernate your computer. It supports hooks before and after suspending.
powerctl https://sr.ht/~sircmpwn/powerctl/ A simple command line utility to control power states on Linux i.e. to suspend or hibernate the system.
pm-utils https://pm-utils.freedesktop.org/wiki/ Collection of scripts that handle suspend and resume on behalf of HAL

Busybox acpid

BusyBox acpid allows custom mapping and handling of ACPI events via options -M FILE (Map file) and -a FILE (Action file).

Map file

A Map file maps ACPI events to descriptions (the last column). For example:

Contents of /etc/acpi.map

"EV_KEY" 0x01 "KEY_POWER" 116 1 "button/power PWRF 00000080" "EV_KEY" 0x01 "KEY_POWER" 116 1 "button/power PWRB 00000080" "EV_KEY" 0x01 "KEY_SLEEP" 142 1 "button/sleep SBTN 00000080" "EV_KEY" 0x01 "KEY_SUSPEND" 205 1 "button/suspend SUSP 00000080" "EV_SW" 0x05 "SW_LID" 0 0 "button/lid LID/open 00000080 00000000" "EV_SW" 0x05 "SW_LID" 0 1 "button/lid LID/close 00000080 00000001" "EV_SW" 0x05 "SW_TABLET_MODE" 1 0 "video/tabletmode TBLT/off 0000008A 00000000" "EV_SW" 0x05 "SW_TABLET_MODE" 1 1 "video/tabletmode TBLT/on 0000008A 00000001"

The built-in map file contains only PWRB/PWRF (power button) and LID (lid close).

Action file

An Action file maps the event descriptions specified in the Map file to action scripts relative to the Config directory (/etc/acpi by default). It performs a substring match, so typically only the second part of the description is specified in the Action file. If the target path is not a file, but directory, it executes all scripts in the directory via run-parts. For example:

Contents of /etc/acpid.conf

PWRF power SBTN sleep SUSP suspend LID/open lid/open LID/close lid/close TBLT/off tabletmode/off TBLT/on tabletmode/on

When the power button is pressed, acpid runs script /etc/acpi/power.

Suspend when closing the LID

There are a few ways to suspend a laptop when closing the LID of it.

Installing a power management utility like zzz along with acpid package provides full support for pre/post suspend hooks etc. The default handler script (/etc/acpi/handler.sh) installed with the package acpid package provides out of the box support for suspend on LID closure.

Alternately, this can be achieved using Busybox acpid with a hook in /etc/acpi/LID/00000080. Make the hook executable:

# chmod +x /etc/acpi/LID/00000080

Ensure that the acpid daemon service is running.

Configuring with zzz:

Contents of /etc/acpi/LID/00000080

#!/bin/sh exec zzz

Configuring with pm-utils:

Contents of /etc/acpi/LID/00000080

#!/bin/sh exec pm-suspend

Configuring with raw variant:

Contents of /etc/acpi/LID/00000080

#!/bin/sh echo mem > /sys/power/state

elogind and power management

If elogind is used, add the following line to /etc/doas.conf config file

Contents of /etc/doas.conf

... permit nopass $USER as root cmd /bin/loginctl

You should now be able to suspend as a normal user, using the full path to executable. Refer to elogind page for more detailed information.

Handling the pressing of power button

In case of desktop environments, it might be useful to allow for some control on what happens when you press the power button instead of shutting down the computer.

BusyBox acpid

This can be done via inbuilt BusyBox acpid by creating/modifying the hook in /etc/acpi/PWRF/00000080. Make the hook executable:

# chmod +x /etc/acpi/PWRF/00000080

Ensure that the acpid daemon service is running.

Configuring for shutdown

In a newly installed system this might be already defined, however you can create the hook as follows:

Contents of /etc/acpi/PWRF/00000080

#!/bin/sh poweroff

Configuring for sleep

Use one of the power management utility, say zzz here and Modify the hook as follows:

Contents of /etc/acpi/PWRF/00000080

#!/bin/sh zzz

Disabling the power button

To disable simply comment or remove the hook. This is useful to allow desktop environments like Gnome or KDE to handle the power button.

Contents of /etc/acpi/PWRF/00000080

#!/bin/sh #Nothing

acpid2

The acpid daemon provided by the acpid package also allows configuring what actions will be taken when the power button is pressed.

The more straightforward way to configure it is to edit the provided handler script included in the package, /etc/acpi/handler.sh. You can also configure separate scripts and event files if you prefer simpler scripts.

Configuring relative to device type (default)

By default, the handler script will suspend if the device has a lid, which implies it is a laptop. Otherwise, it will poweroff:

Contents of /etc/acpi/handler.sh

... log 'Power button pressed' # If we have a lid (notebook), suspend to RAM, otherwise power off. if [ -e /proc/acpi/button/lid/LID ]; then suspend else poweroff fi ;; ...

Configuring for shutdown

Replace the if ... fi statement above with just poweroff:

Contents of /etc/acpi/handler.sh

... log 'Power button pressed' poweroff ;; ...

Configuring for sleep

The same can be applied to configure the machine to sleep:

Contents of /etc/acpi/handler.sh

... log 'Power button pressed' suspend ;; ...

Note that the suspend command above is provided by the script, and not a system command. If you are writing your own script, you should replace it with your power management utility of choice.

Disabling the power button

To disable the button instead, leave out the log call only, if you want the event to still get logged. Otherwise, you can also comment out or remove the case branch entirely.

Contents of /etc/acpi/handler.sh

... log 'Power button pressed' ;; ...

After making changes to the script, they will only take effect once you restart the acpid daemon:

# rc-service acpid restart

acpid2 custom scripts and event files

When using acpid2 from the acpid package, the provided handler.sh acts a catch-all for all supported events: power button presses, lid open and close, power plug connection, among others. While this is convenient as a default and for simple modifications, you can also separate scripts from event declarations and manage them independently, using event files to declare which scripts apply to which events.

A minimal /etc/acpi directory could look like this:

/etc/acpi ├── events | └── anything └── handler.sh

However, depending on your previous use of BusyBox acpid and package upgrades after modifying the handler script, you could also have the following structure:

/etc/acpi ├── PWRF |   └── 00000080 ├── events |   └── anything ├── handler.sh └── handler.sh.apk-new

The PWRF directory is a leftover from BusyBox acpid and the handler.sh.apk-new file was left by apk during an upgrade so as not to overwrite your configuration. These are harmless to keep, since acpid2 only concerns itself with /etc/acpi/events and the paths specified within it. You can also remove them, however, since you are likely keeping BusyBox acpid in your system as part of BusyBox, keeping its configuration can also serve as a safer fallback.

Inside /etc/acpi/events, we can define event files that specify what events they apply to and what action should be taken when these events happen. The action is specified in the form of a path to a script.

In the case of the default handler.sh script, we have a single "anything" event that matches any event through the regular expression .*:

Contents of /etc/acpi/events/anything

# Pass all events to our one handler script event=.* action=/etc/acpi/handler.sh %e

The event value is a regular expression that can match one or more event names and the action value is a command that will be interpreted by /bin/sh.

To identify event names, see the corresponding section.

We can create any other event file under /etc/acpi/events that refers to a script file in /etc/acpi. Consider the following example, adapted from the acpid man page to the Alpine context:

Contents of /etc/acpi/power.sh

logger -t acpid "Power button pressed" /sbin/poweroff

Contents of /etc/acpi/events/power

event=button/power action=/etc/acpi/power.sh "%e"

In this example, any event containing button/power is configured to trigger the /etc/acpi/power.sh script with the full event name as an argument. The /etc/acpi/power.sh script simply logs the event and then shuts the system down by calling /sbin/poweroff.

acpid will parse all event files on startup and, when a matching event is detected, it will take all actions that match that event. This means multiple event files can match, allowing you to call more than one script for a given event or set of events.

When matching the event name, the regular expression provided in the event file will match the event even for partial matches. If you prefer to match the whole command name exactly, wrap it in ^ and $:

Contents of /etc/acpi/events/ac

event=^ac_adapter ACPI0003:00 00000080 00000000$ action=/etc/acpi/ac_off.sh %e

The special sequence %e is replaced by the actual, full event name. This allows you to handle different events in specific ways in a single script.

Identifying event names

The name of events can vary depending on your hardware. The acpid package also provides the acpi_listen utility, which you can use to check what event names are the ones produced in your system.

To use it, run the acpi_listen command and then perform some action, such as closing the lid or unplugging the power cable. The corresponding event will appear in the command output:

$ acpi_listen button/lid LID close button/lid LID open

Note that this will not prevent acpid from actually handling this event and taking whatever action it is configured to take.

See also