From ArchWiki
Revision as of 14:18, 4 June 2015 by Alad (talk | contribs) (Connect to acpid socket: use read -a to use an array, that way we can use the same format as (split string))
Jump to: navigation, search


acpid2 is a flexible and extensible daemon for delivering ACPI events. When an event occurs, executes programs to handle the event. These events are triggered by certain actions, such as:

  • Pressing special keys, including the Power/Sleep/Suspend button
  • Closing a notebook lid
  • (Un)Plugging an AC power adapter from a notebook
  • (Un)Plugging phone jack etc.
Note: Desktop environments, such as GNOME, systemd login manager and some extra key handling daemons may implement own event handling schemes, independent of acpid. Running more than one system at the same time may lead to unexpected behaviour, such as suspending two times in a row after one sleep button press. You should be aware of this and only activate desirable handlers.


Install the acpid package, available in the official repositories.

To have acpid started on boot, enable acpid.service.


acpid comes with a number of predefined actions for triggered events, such as what should happen when you press the Power button on your machine. By default, these actions are defined in /etc/acpi/, which is executed after any ACPI events are detected (as determined by /etc/acpi/events/anything).

The following is a brief example of one such action. In this case, when the Sleep button is pressed, acpid runs the command echo -n mem >/sys/power/state which should place the computer into a sleep (suspend) state:

    case "$2" in
        SLPB) echo -n mem >/sys/power/state ;;
	 *)    logger "ACPI action undefined: $2" ;;

Unfortunately, not every computer labels ACPI events in the same way. For example, the Sleep button may be identified on one machine as SLPB and on another as SBTN.

To determine how your buttons or Fn shortcuts are recognized, run the following command:

# journalctl -f

Now press the Power button and/or Sleep button (e.g. Fn+Esc) on your machine. The result should look something this:

logger: ACPI action undefined: PBTN
logger: ACPI action undefined: SBTN

If that does not work, run:

# acpi_listen

or with openbsd-netcat:

$ netcat -U /var/run/acpid.socket

Then press the power button and you will see something like this:

power/button PBTN 00000000 00000b31

The output of acpi_listen is sent to /etc/acpi/ as $1, $2 , $3 & $4 parameters. Example:

$1 power/button
$3 00000000
$4 00000b31

As you might have noticed, the Sleep button in the sample output is actually recognized as SBTN, rather than the SLPB label specified in the default /etc/acpi/ In order for Sleep function to work properly on this machine, we would need to replace SLPB) with SBTN).

Using this information as a base, you can easily customize the /etc/acpi/ file to execute a variety of commands depending on which event is triggered. See the Tips & Tricks section below for other commonly used commands.

Alternative configuration

By default, all ACPI events are passed through the /etc/acpi/ script. This is due to the ruleset outlined in /etc/acpi/events/anything:

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

While this works just fine as it is, some users may prefer to define event rules and actions in their own self-contained scripts. The following is an example of how to use an individual event file and corresponding action script:

As root, create the following file:

event=button sleep.*
action=/etc/acpi/actions/ %e

Now create the following file:

case "$3" in
    SLPB) echo -n mem >/sys/power/state ;;
    *)    logger "ACPI action undefined: $3" ;;

Finally, make the script executable:

# chmod +x /etc/acpi/actions/

Using this method, it is easy to create any number of individual event/action scripts.

Tips and tricks

Note: Some of actions, described here, such as Wi-Fi toggle and backlight control, may already be managed directly by driver. You should consult documentation of corresponding kernel modules, when this is the case.

Example events

The following are examples of events that can be used in the /etc/acpi/ script. These examples should be modified so that they apply your specific environment e.g. changing the event variable names interpreted by acpi_listen.

To set the laptop screen brightness when plugged in power or not (the numbers might need to be adjusted, see /sys/class/backlight/acpi_video0/max_brightness):

    case "$2" in
            case "$4" in
                    echo -n 50 > /sys/class/backlight/acpi_video0/brightness
                    echo -n 100 > /sys/class/backlight/acpi_video0/brightness

Enabling volume control

Find out the acpi identity of the volume buttons (see above) and susbtitute it for the acpi events in the files below.

action=amixer set Master 5-
action=amixer set Master toggle
action=amixer set Master 5+

Enabling backlight control

Similar to volume control, acpid also enables you to control screen backlight. To achieve this you write some handler, like this:


case $1 in
  -) echo $(($(< $bl_dev/brightness) - $step)) >$bl_dev/brightness;;
  +) echo $(($(< $bl_dev/brightness) + $step)) >$bl_dev/brightness;;

and again, connect keys to ACPI events:

action=/etc/acpi/handlers/bl -
action=/etc/acpi/handlers/bl +

Enabling Wi-Fi toggle

You can also create a simple wireless-power switch by pressing the WLAN button. Example of event:


and its handler:


case $(< $rf/state) in
  0) echo 1 >$rf/state;;
  1) echo 0 >$rf/state;;

Laptop monitor power off

Merge-arrows-2.pngThis article or section is a candidate for merging with #Getting user name of the current display.Merge-arrows-2.png

Notes: please use the second argument of the template to provide more detailed indications. (Discuss in Talk:Acpid#)

Add this to the button/lid section of /etc/acpi/ This will turn off the LCD back-light when the lid is closed, and restart when the lid is opened.

case $(awk '{print $2}' /proc/acpi/button/lid/LID0/state) in
    closed) XAUTHORITY=$(ps -C xinit -f --no-header | sed -n 's/.*-auth //; s/ -[^ ].*//; p') xset -display :0 dpms force off ;;
    open)   XAUTHORITY=$(ps -C xinit -f --no-header | sed -n 's/.*-auth //; s/ -[^ ].*//; p') xset -display :0 dpms force on  ;;

If you would like to increase/decrease brightness or anything dependent on X, you should specify the X display as well as the MIT magic cookie file (via XAUTHORITY). The last is a security credential providing read and write access to the X server, display, and any input devices.

Here is another script not using XAUTHORITY but sudo:

case $(awk '{print $2}' /proc/acpi/button/lid/LID0/state) in
    closed) sudo -u $(ps -o ruser= -C xinit) xset -display :0 dpms force off ;;
    open)   sudo -u $(ps -o ruser= -C xinit) xset -display :0 dpms force on  ;;

With certain combinations of Xorg and stubborn hardware, xset dpms force off only blanks the display leaving the backlight turned on. This can be fixed using vbetool from the official repositories. Change the LCD section to:

case $(awk '{print $2}' /proc/acpi/button/lid/LID0/state) in
    closed) vbetool dpms off ;;
    open)   vbetool dpms on  ;;

If the monitor appears to shut off only briefly before being re-powered, very possibly the power management shipped with xscreensaver conflicts with any manual dpms settings.

Getting user name of the current display

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

Reason: Not a very robust method, stands or falls with a correctly configured startx. It would also be nice to have a function which runs (or rather repeats) an action for all current users. (Discuss in Talk:Acpid#)

You can use the function getuser to discover the user of the current display:

    who=$(w -sh | grep tty$(fgconsole))
    user=$(echo "$who" | awk '{ print $1 }')
    if [[ $user ]]; then
        export XAUTHORITY="/home/$user/.Xauthority"
        export DISPLAY=$(echo "$who" | grep -o " :[[:digit:]]" | tr -d ' ')
        sudo -u "$user" "$@"
        return 1

If this fails, make sure /run/utmp is created at boot-time; see man utmp for details.

With systemd, you may use loginctl to obtain the required information, e.g. through xuserrun-gitAUR from the AUR.

Connect to acpid socket

In addition to rule files, acpid accepts connections on a UNIX domain socket, by default /var/run/acpid.socket. User applications may connect to this socket. With openbsd-netcat:

nc -U /var/run/acpid.socket |
    while read -a event; do ${event[@]}

Where can be a script similar to /etc/acpi/

See also