acpid

出自 Arch Linux 中文维基

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

  • 按下電源按鈕
  • 按下睡眠/掛起按鈕
  • 合上筆記本蓋子
  • 拔下/插上筆記本外接電源
警告: 請注意桌面環境比如GNOMEsystemd額外按鍵處理進程會有它自己的一套管理方法。同時運行多套系統可能產生意想不到的結果,比如,當按下電源鍵時電腦同時執行掛起和關機;或者當按下睡眠按鈕時電腦執行了兩次掛起操作。所以,使用多套系統時你應只激活一套系統的電源事件管理方法,以免引起衝突。

安裝[編輯 | 編輯原始碼]

使用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.shSLPB)替換為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
	;;

參考[編輯 | 編輯原始碼]