acpid (简体中文)

From ArchWiki
Revision as of 02:57, 5 October 2012 by Cael (talk | contribs) (sync with the english version)
Jump to navigation Jump to search

翻译状态: 本文是英文页面 Acpid翻译,最后翻译时间:2012-09-28,点击这里可以查看翻译后英文页面的改动。

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

  • 按下电源按钮
  • 按下睡眠/挂起按钮
  • 合上笔记本盖子
  • 拔下/插上笔记本外接电源

acpid可以单独自己运行也可以配合一个更强健的系统(比如 pm-utilscpufrequtils)来提供一个更完善的电源管理方案。

Warning: Please note that desktop environments such as GNOME tend to have their own means of handling ACPI events, independent of acpid. The systemd login manager implements its own system , too. Running more than one system at the same time may lead to unexpected behaviour. For example suspending and shutting down at the same time, when the power button is pressed or suspending two times in a row after one sleep button press. You should be aware of this and only activate event handlers in one configuration system, completely disabling them in the others.
警告: 请注意桌面环境比如GNOME倾向于使用自己的电源事件管理方法(独立于acpid),[systemd (简体中文)
KDE SC and GNOME用户请注意: 由于acpid提供的脚本/etc/acpi/handler.sh会覆盖掉桌面环境的电源按钮的功能, 为了避免当按下电源按钮时你的电脑突然关机(这是很烦人的而且可能会造成资料损失因为它在关机前不会等待你先保存你目前的工作),你最好禁用掉acpid对电源按钮的管理。要禁用的话,只需编辑/etc/acpi/handler.sh,用"#"注释掉第15行。

安装

acpid官方软件仓库中,你可以使用Pacman来安装它。

你可以用root身份编辑/etc/rc.conf把{ic|acpid}}加入DAEMONS array中来让它开机自动运行。

配置

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

要想确定各种按钮或Template:Keypress快捷键在你的计算机上是如何定义的,以root身份在终端运行:

# tail -f /var/log/messages.log

现在在你计算机上按下电源按钮或睡眠按钮(比如Template:Keypress),你会得到类似以下的结果:

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

如果这不起作用的话,运行:

# acpi_listen

然后按下电源按钮,你会看到类似以下输出:

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.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 "$2" in
    SLPB) echo -n mem >/sys/power/state ;;
    *)    logger "ACPI action undefined: $2" ;;
esac

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

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

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

小技巧

用pm-utils扩展acpid

虽然acpid可以提供基本的挂起功能,你可能需要一个更强健的挂起方案。pm-utils为挂起和休眠提供了一个非常灵活的框架,能够修复挂起或休眠引起的一些顽固的硬件或驱动方面的问题。pm-utils提供了两个脚本,pm-suspendpm-hibernate。这两个脚本都可以在acpid中被调用,更多信息请参考pm-utils

脚本示例

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

实现当按下睡眠按钮时执行pm-suspend

button/sleep)
    case "$2" in
        SBTN) 
	     #echo -n mem >/sys/power/state
            /usr/sbin/pm-suspend
            ;;

实现插拔外接电源时自动设置屏幕亮度(数值可能需要调整,参考/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.shbutton/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
    ;;

参考