acpid (简体中文)
相关文章
acpid是用于处理电源相关事件的守护进程,它非常灵活且易于扩展。它侦听/proc/acpi/event,当某个事件发生时,执行相关程序来处理该事件。这些事件是由某些动作触发的,比如:
- 按下电源按钮
- 按下睡眠/挂起按钮
- 合上笔记本盖子
- 拔下/插上笔记本外接电源
安装
acpid在官方软件仓库中,你可以使用Pacman来安装它。
To have acpid started on boot, enable 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快捷键在你的计算机上是如何定义的,以root身份在终端运行:
# journalctl -f
现在在你计算机上按下电源按钮或睡眠按钮(比如Fn+Esc),你会得到类似以下的结果:
logger: ACPI action undefined: PBTN logger: ACPI action undefined: SBTN
如果这不起作用的话,运行:
# acpi_listen
$ netcat -U /var/run/acpid.socket
然后按下电源按钮,你会看到类似以下输出:
power/button PBTN 00000000 00000b31
acpi_listen的输出会被作为$1, $2 , $3 & $4参数发送给/etc/acpi/handler.sh。
举例:
$1 power/button $2 PBTN $3 00000000 $4 00000b31
像你看到的那样,在这个例子中睡眠按钮被识别为SBTN,而不是SLPB(这是/etc/acpi/handler.sh中默认定义的标识符)。所以,要想让你的睡眠按钮正常工作的话,你需要编辑/etc/acpi/handler.sh把SLPB)替换为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侦测到的那个。
实现合上笔记本盖子时使用xscreensaver锁屏:
button/lid)
case $3 in
close)
# The lock command need to be run as the user who owns the xscreensaver process and not as root.
# See: man xscreensaver-command. $xs will have the value of the user owning the process, if any.
xs=$(ps -C xscreensaver -o user=)
if test $xs; then su $xs -c "xscreensaver-command -lock"; fi
;;
实现合上笔记本盖子时挂起系统并用slimlock锁屏:
button/lid)
case $3 in
close)
#echo "LID switched!">/dev/tty5
/usr/sbin/pm-suspend &
DISPLAY=:0.0 su -c - username /usr/bin/slimlock
;;
实现插拔外接电源时自动设置屏幕亮度(数值可能需要调整,参考/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
音量调整
下面的一系列脚本是用来控制音量的(假设你用的是ALSA)。用上面讲到的方法找到音量键的标识符,然后替换掉下面文件中的事件标识就可以用在自己电脑上了:
/etc/acpi/actions/volume_up.sh
#!/bin/bash /usr/bin/amixer set Master 5%+
/etc/acpi/actions/volume_down.sh
#!/bin/bash /usr/bin/amixer set Master 5%-
定义事件的文件:
/etc/acpi/events/volume_up
event=button[ /]volumeup action=/etc/acpi/actions/volume_up.sh
/etc/acpi/events/volume_down
event=button[ /]volumedown action=/etc/acpi/actions/volume_down.sh
用于切换静音的配置文件:
/etc/acpi/events/volume_mute
event=button[ /]volumemute action=/usr/bin/amixer set Master toggle
关闭笔记本显示器
下面这个小技巧修改自 Gentoo wiki。把下面的内容添加到/etc/acpi/actions/lm_lid.sh最后,或者添加到/etc/acpi/handler.sh的button/lid部分。这个配置会实现当合上笔记本盖子时自动切断LCD背光,揭开盖子时自动打开LCD背光。
case $(cat /proc/acpi/button/lid/LID0/state | awk '{print $2}') 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 ;;
esac
如果你想提高、降低亮度或做其他一些跟X有关的事情,你应当明确指定你的X显示接口以及那个神奇的MIT cookie文件(一个用于对X服务器和其它输入设备进行读写访问的安全凭证)。
下面的脚本没有用到XAUTHORITY,使用了sudo:
case $(cat /proc/acpi/button/lid/LID0/state | awk '{print $2}') 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 ;;
esac
在一些难缠的硬件上当使用某些版本的Xorg时,xset dpms force off只会使屏幕变黑并不会关闭屏幕背光。这个bug可以用 vbetool(来自official repositories)来修复。做以下更改:
case $(cat /proc/acpi/button/lid/LID0/state | awk '{print $2}') in
closed) vbetool dpms off ;;
open) vbetool dpms on ;;
esac
如果显示器只是快速的关闭然后又打开,很可能是xscreensaver自带的电源管理跟dpms的设置冲突了。
获取当前登陆的用户名
你可以使用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
;;
ACPI 快捷键
您可以直接编辑/etc/acpi/handler.sh, 将快捷键反应到ACPI事件, 或者您也可以将这些快捷键指向别的自己定义的一些脚本 (例如: /etc/acpi/hotkeys.sh)
在这行之下
case "$1" in
添加如下行的内容:
hkey) case "$4" in 00000b31) echo "PreviousButton pressed!" exailectl p ;; 00000b32) echo "NextButton pressed!" exailectl n ;; 00000b33) echo "Play/PauseButton pressed!" exailectl pp echo "executed.." ;; 00000b30) echo "StopButton pressed!" exailectl s ;; *) echo "Hotkey Else: $4" ;; esac ;;
这个 '00000b31' 之类的值就是通过acpi_listen监听到的快捷键的值. 在acpi_listen监听到的值中'hkey VALZ 00000000 00000b31', $4也就是最后部分, 就是区别于其他键的部分.
并且,我为了控制Exaile音乐播放器写了一个简单的 exailectl 脚本. 因为ACPID是在root级别的守护进程, 所以您需要用下面方式来写控制脚本
sudo -u (用户名) exaile
不然的话,快捷键的动作不会检测到您的用户正在运行的程序,它就会去重新启动另一个程序而不是对当前的程序作出反应.
参考
- http://acpid.sourceforge.net/ - acpid homepage
- Gentoo wiki
- ACPI hotkeys