acpid - Arch Linux 中文维基

跳至內容

# acpid

出自 Arch Linux 中文维基

翻譯狀態：

- 本文（或部分內容）譯自 Acpid，最近一次同步於 2022-12-17，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- ACPI modules
- DSDT

acpid2是用於處理電源相關事件的守護進程，它非常靈活且易於擴展。當某個事件發生時，執行相關程序來處理該事件。這些事件是由某些動作觸發的，比如：

- 按下電源按鈕
- 按下睡眠/掛起按鈕
- 合上筆記本蓋子
- 拔下/插上筆記本外接電源

警告：請注意桌面環境比如GNOME，systemd 和 額外按鍵處理進程會有它自己的一套管理方法。同時運行多套系統可能產生意想不到的結果，比如，當按下電源鍵時電腦同時執行掛起和關機；或者當按下睡眠按鈕時電腦執行了兩次掛起操作。所以，使用多套系統時你應只激活一套系統的電源事件管理方法，以免引起衝突。

## 安裝

使用Pacman 安裝 acpid包。 然後 start/enable `acpid.service`.

## 配置

### 確定事件名稱

不幸的是計算機上的這些電源事件標識並不統一，比如，在一些計算機上睡眠按鈕可能被標識為SLPB，而在另一些計算機上為SBTN。

要想確定各種按鈕或`Fn`快捷鍵在你的計算機上是如何定義的：

    # journalctl -f

現在在你計算機上按下電源按鈕或睡眠按鈕（比如`Fn+Esc`），你會得到類似以下的結果：

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

如果這不起作用的話，運行：

    # acpi_listen

或者openbsd-netcat包：

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

然後按下電源按鈕，你會看到類似以下輸出：

    button/power PBTN 00000000 00000b31

`acpi_listen`的輸出會被作為$1, $2 , $3 & $4參數發送給`/etc/acpi/handler.sh`。 舉例：

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

### 定義事件動作

acpid包預置了許多事件觸發行為，比如它定義了當你按下電源按鈕時應當發生什麼。這些觸發行為默認在`/etc/acpi/handler.sh`中定義。在`/etc/acpi/events/anything`)規定：任何偵測到的電源事件都會按照`/etc/acpi/handler.sh`中定義的觸發行為執行相關動作。

下面是一個定義觸發行為的簡單例子。在這個例子中，當按下睡眠按鈕時acpid運行命令`echo -n mem >/sys/power/state`，這將會使你的電腦掛起：

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

如果睡眠按鈕被識別為SBTN，而不是 `/etc/acpi/handler.sh`中默認定義的 SLPB（這是標識符）。需要編輯`/etc/acpi/handler.sh`把SLPB)替換為SBTN)。

參照上面的例子，你應該可以很容易的通過定製`/etc/acpi/handler.sh`來根據偵測到的電源時間來執行不同的命令。更多例子可參考下面的小技巧部分。

注意：Events such as `button/power`, `button/lid`, `button/suspend` and `button/hibernate` are handled by systemd-logind.service(8) by default, see Power management#Power management with systemd. If handling these events with acpid, the handling of these events by logind should either be disabled first, or inhibited.

### 其它配置方案

默認所有的電源事件都是交由`/etc/acpi/handler.sh`處理的。這是由`/etc/acpi/events/anything`規定的：

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

儘管這樣配置工作起來沒有任何問題，但一些用戶可能更喜歡使用各自獨立的腳本來定義不同的電源事件。下面舉例說明了如何使用不同的事件定義文件和行為定義文件：

作為root，創建以下文件：

    /etc/acpi/events/sleep-button

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

然後建立以下文件：

    /etc/acpi/actions/sleep-button.sh

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

最後，給腳本加上 executable 可執行權限： 並 reload `acpid.service`。

這種方法可以簡化的獨立事件和行為腳本的處理。

## 小技巧

注意：一些在這裡描述的動作，例如無線網絡切換和背光控制，可能已經由驅動直接管理。在這種情況下，您應該查詢相應的內核模塊。

### 腳本示例

下面給出的例子可以用在你的`/etc/acpi/handler.sh`腳本中，只是在使用的時候記得將事件變量更改為`acpi_listen`偵測到的那個。

實現插拔外接電源時自動設置屏幕亮度（數值可能需要調整，參考`/sys/class/backlight/acpi_video0/max_brightness`）：

    ac_adapter)
        case "$2" in
            AC*|AD*)
                case "$4" in
                    00000000)
                        echo -n 50 > /sys/class/backlight/acpi_video0/brightness
                        ;;
                    00000001)
                        echo -n 100 > /sys/class/backlight/acpi_video0/brightness
                        ;;
                esac

### Enabling backlight control

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

    /etc/acpi/handlers/bl

    #!/bin/sh
    bl_dev=/sys/class/backlight/acpi_video0
    step=1

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

and again, connect keys to ACPI events:

    /etc/acpi/events/bl_d

    event=video/brightnessdown.*
    action=/etc/acpi/handlers/bl -

    /etc/acpi/events/bl_u

    event=video/brightnessup.*
    action=/etc/acpi/handlers/bl +

### 音量調整

下面的一系列腳本是用來控制音量的。用上面講到的方法找到音量鍵的標識符，然後替換掉下面文件中的事件標識就可以用在自己電腦上了：

    /etc/acpi/events/vol-d

    event=button/volumedown
    action=amixer set Master 5-

    /etc/acpi/events/vol-m

    event=button/mute
    action=amixer set Master toggle

    /etc/acpi/events/vol-u

    event=button/volumeup
    action=amixer set Master 5+

注意：這些命令在 PulseAudio 下可能有問題[1]。要實現全部功能，以當前用戶執行並將設置 `XDG_RUNTIME_DIR` 環境變量 environment variable,例如 `# sudo -u user XDG_RUNTIME_DIR=/run/user/1000 pactl`.
提示：在 Xorg 中禁用或綁定這些音量按鍵，以避免和其他程序衝突。詳情請參考或 Xmodmap.

參閱 [2].

### Disabling ordinary key events

Since b336c96 acpid generates events for some ordinary key presses, such as arrow keys. This results in event/handler spam, visible in system logs or top. Events for these buttons can be dropped in the configuration file:

    /etc/acpi/events/buttons

    event=button/(up|down|left|right|kpenter)
    action=<drop>

### 獲取當前登錄的用戶名

你可以使用`getuser`函數來獲取當前登錄的用戶名：

    getuser ()
        {
         export DISPLAY=`echo $DISPLAY | cut -c -2`
         user=`who | grep " $DISPLAY" | awk '{print $1}' | tail -n1`
         export XAUTHORITY=/home/$user/.Xauthority
         eval $1=$user
        }

然後這個函數就可以被用在下面的例子中，它可以在你按下電源按鈕時正常的關閉KDE：

    button/power)
        case "$2" in
            PBTN)
                getuser "$user"
                echo $user > /dev/tty5
                su $user -c "dcop ksmserver ksmserver logout 0 2 0"
                ;;
              *) logger "ACPI action undefined $2" ;;
        esac
        ;;

#### 連接到 acpid 套接字

除了規則文件之外，acpid 也接受 UNIX 域套接字連接，默認是 `/var/run/acpid.socket`. 用戶程序可以連接到此套接字。

    #!/bin/bash
    coproc acpi_listen
    trap 'kill $COPROC_PID' EXIT

    while read -u "${COPROC[0]}" -a event; do
        handler.sh "${event[@]}"
    done

handler.sh 可以參考 `/etc/acpi/handler.sh`.

### Disable keyboard and touchpad while laptop lid is closed under Wayland

This example uses inhibited property of input device drivers as a replacement for xinput which does not work under Wayland.

    	button/lid)
    		if echo "$3" | grep -iq "open"; then
    			echo 'LID opened'
    			disabled=0
    		fi
    		if echo "$3" | grep -iq "close"; then
    			echo 'LID closed'
    			disabled=1
    		fi
    		find /sys/devices/platform/i8042/serio* -prune -type d | while IFS= read -r serionumber; do
    			find $serionumber/input/* -prune -type d | while IFS= read -r inputdevicepath; do
    				if grep -q -i -e "keyboard" -e "touchpad" $inputdevicepath/name; then
    					logger "found $(cat $inputdevicepath/name) and set to $disabled"
    					echo $disabled > $inputdevicepath/inhibited
    				fi
    			done
    		done
    	;;

## 參考

- http://acpid.sourceforge.net/ - acpid 主頁
- Gentoo:ACPI#Configuration

分類：​

- 電源管理

acpid
新增話題