acpid (简体中文)

From ArchWiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

翻译状态:本文是 Acpid翻译。上次翻译日期:2017-08-18。如果英文版本有所更改,则您可以帮助同步翻译。

acpid2是用于处理电源相关事件的守护进程,它非常灵活且易于扩展。当某个事件发生时,执行相关程序来处理该事件。这些事件是由某些动作触发的,比如:

  • 按下电源按钮
  • 按下睡眠/挂起按钮
  • 合上笔记本盖子
  • 拔下/插上笔记本外接电源
警告: 请注意桌面环境比如GNOMEsystemd额外按键处理进程会有它自己的一套管理方法。同时运行多套系统可能产生意想不到的结果,比如,当按下电源键时电脑同时执行挂起和关机;或者当按下睡眠按钮时电脑执行了两次挂起操作。所以,使用多套系统时你应只激活一套系统的电源事件管理方法,以免引起冲突。

安装

使用Pacman 安装 acpid。 然后 startenable acpid.service.

配置

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

不幸的是计算机上的这些电源事件标识并不统一,比如,在一些计算机上睡眠按钮可能被标识为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

像你看到的那样,在这个例子中睡眠按钮被识别为SBTN,而不是SLPB(这是/etc/acpi/handler.sh中默认定义的标识符)。所以,要想让你的睡眠按钮正常工作的话,你需要编辑/etc/acpi/handler.shSLPB)替换为SBTN)

参照上面的例子,你应该可以很容易的通过定制/etc/acpi/handler.sh来根据侦测到的电源时间来执行不同的命令。更多例子可参考下面的小技巧部分。

其它配置方案

默认所有的电源事件都是交由/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

最后,给脚本加上可执行权限:

# chmod +x /etc/acpi/actions/sleep-button.sh

用这种方法,你可以任意的独立的事件/行为脚本。

小技巧

注意: 一些在这里描述的动作,例如无线网络切换和背光控制,可能已经由驱动直接管理。在这种情况下,您应该查询相应的内核模块。

脚本示例

下面给出的例子可以用在你的/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

音量调整

下面的一系列脚本是用来控制音量的。用上面讲到的方法找到音量键的标识符,然后替换掉下面文件中的事件标识就可以用在自己电脑上了:

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

获取当前登陆的用户名

你可以使用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.

参考