acpid

提供: ArchWiki
2017年1月29日 (日) 00:35時点におけるKusakata (トーク | 投稿記録)による版 (文字列「[[zh-CN:」を「[[zh-hans:」に置換)
移動先: 案内検索

acpid2ACPI イベントを伝える、柔軟性と拡張性があるデーモンです。イベントが発生すると、そのイベントを処理するプログラムを実行します。イベントは以下のようなアクションによって引き起こされます:

  • Power/Sleep/Suspend ボタンなど、特殊なキーを押す
  • ノートパソコンのフタを閉じる
  • ノートパソコンに AC 電源アダプタを接続 (切断) する
  • イヤフォンジャックを接続 (切断) する
ノート: GNOME などのデスクトップ環境systemd のログインマネージャ、追加のキーを管理するデーモンなどは acpid を使わずに、独自のイベント処理機構を実装していることがあります。同時に複数のシステムを実行すると、sleep ボタンを押した時にサスペンドが二回連続で実行されるなど、予期しない動作が起こる可能性が存在します。このことについては十分注意をして必要な処理システムだけを有効にしてください。

インストール

公式リポジトリacpid パッケージをインストールしてください。

ブート時に acpid を起動させるには、acpid.service有効化します。

設定

acpid には発生したイベントについて定義済みのアクションが多数付属しています。例えばマシンの電源ボタンを押した時に起こることなどです。デフォルトでは、これらのアクションは /etc/acpi/handler.sh に定義されており、ACPI イベントが検出されると実行されます (/etc/acpi/events/anything によって判断されます)。

以下はそうしたアクションの簡単なサンプルです。以下の場合、Sleep ボタンが押されたときに、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
    ;;

残念ながら、全てのコンピュータで同じ方法によって ACPI イベントが分類されているわけではありません。例えば、Sleep ボタンはマシンによって SLPB とか SBTN として認識されることがあります。

ボタンや Fn ショートカットがどうやって認識されているのか確認するには、root でターミナルから次のコマンドを実行します:

# journalctl -f

そしてマシンの Power ボタンや Sleep ボタン (例: Fn+Esc) を押してみて下さい。結果は以下のようになるはずです:

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

上記が動作しない場合は、次を実行してください:

# acpi_listen

もしくは openbsd-netcat を使用:

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

そして power ボタンを押して下さい。次のような表示がされます:

button/power PBTN 00000000 00000b31

acpi_listen の出力は $1, $2 , $3, $4 パラメータとして /etc/acpi/handler.sh に送られます。サンプル:

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

気づいたかもしれませんが、上のサンプルの出力で Sleep ボタンは、デフォルトの /etc/acpi/handler.sh で指定されている SLPB ラベルではなく、実際は SBTN として認識されています。このマシンで Sleep 機能を正しく動作させるために、SLPB)SBTN) で置き換える必要があるということです。

以上の情報を元にして、/etc/acpi/handler.sh ファイルをカスタマイズすることで、発生するイベントに応じて色々なコマンドを簡単に実行することができます。他のよく使われるコマンドについては下の Tips & Tricks セクションを見て下さい。

別の設定

デフォルトでは、全ての ACPI イベントは /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

この方法を使えば、個別のイベント/アクションスクリプトをいくらでも簡単に作成できます。

Tips and tricks

ヒント: 以下に記載している、Wi-Fi トグルやバックライトコントロールなどのアクションは、ドライバーによって直接管理が行われている可能性があります。その場合、適切なカーネルモジュールのドキュメントを参照してください。

サンプルイベント

以下は /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/bin/pm-suspend &
	     DISPLAY=:0.0 su -c - username /usr/bin/slimlock
            ;;

フタが閉じられたときに gnome-screensaver-command で画面をロックするには:

   button/lid)
       case "$3" in
           close)
               export DISPLAY=:0.0
               for pid in $(pgrep -u username)
               do
                    declare DBUS_SESSION_BUS_ADDRESS=$(cat /proc/${pid}/environ \
                       | tr '\0' '\n' | grep "DBUS_SESSION_BUS_ADDRESS=")
                    [ -z "${DBUS_SESSION_BUS_ADDRESS}" ] || break
               done
               export "$DBUS_SESSION_BUS_ADDRESS"
               su -c - username 'gnome-screensaver-command -l'
               ;;

電源が接続されたときや切断されたときにノートパソコンの画面の明るさを設定するには (おそらく数値は変更する必要があります、/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/handler.shjack/headphone セクションに追加してください。ヘッドホンジャックを差した場合にミュートが解除され、ヘッドホンジャックを抜いた場合にミュートされます。

   jack/headphone)
       case "$3" in
           plug)
               logger 'HEADPHONE pluged'
               /usr/bin/amixer sset Master unmute
               ;;
           unplug)
               logger 'HEADPHONE unpluged'
               /usr/bin/amixer sset Master mute
               ;;
       esac
       ;;

ボリュームコントロールを有効にする

ボリュームボタンの acpi の id を確認して (上を参照)、以下のファイルで acpi イベントの代わりにします。ボリュームをコントロールするスクリプトを作成 (ALSA サウンドカードが前提):

/etc/acpi/handlers/vol
#!/bin/sh
step=5

case $1 in
  -) amixer set Master $step-;;
  +) amixer set Master $step+;;
esac

そして新しい acpi イベントに接続:

/etc/acpi/events/vol_d
event=button/volumedown
action=/etc/acpi/handlers/vol -
/etc/acpi/events/vol_u
event=button/volumeup
action=/etc/acpi/handlers/vol +

さらに、ミュート設定を切り替えるイベントも:

/etc/acpi/events/mute
event=button/mute
action=/usr/bin/amixer set Master toggle
ノート: 上記のコマンドは PulseAudio を使っている場合、上手く動作しない可能性があります。PulseAudio#キーボードのボリュームコントロールを参照。
ヒント: Xorg のボリュームボタンは無効化あるいはバインドして他のアプリケーションと衝突しないようにしてください。詳しくは Xmodmap を見てください。

Fixing volume change in Linux も参照。

バックライトコントロールを有効にする

ボリュームコントロールと同じように、acpid を使えば画面の輝度をコントロールすることができます。輝度のコントロールには、以下のようなハンドラを書きます:

/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

そして、キーを ACPI イベントにつなげます:

/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 +

Wi-Fi トグルを有効にする

WLAN ボタンを押すことによる、シンプルなワイヤレスの電源スイッチを作成することもできます。イベントの例:

/etc/acpi/events/wlan
event=button/wlan
action=/etc/acpi/handlers/wlan

そしてそのハンドラ:

/etc/acpi/handlers/wlan
#!/bin/sh
rf=/sys/class/rfkill/rfkill0

case $(< $rf/state) in
  0) echo 1 >$rf/state;;
  1) echo 0 >$rf/state;;
esac

ノートパソコンのモニターの電源オフ

以下を /etc/acpi/handler.shbutton/lid セクションに追加してください。フタが閉じられたときは LCD バックライトをオフにして、フタが開かれたときはバックライトをオンにします。

case $(awk '{print $2}' /proc/acpi/button/lid/LID0/state) 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 に関連することを増減させたい場合は、MIT マジッククッキーと X display を指定する必要があります (XAUTHORITY を使用)。前者は X サーバーやディスプレイ、入力デバイスなどへの読み書きアクセスを提供するセキュリティ証明です。

以下は XAUTHORITY を使うかわりに sudo を使用するスクリプトです:

case $(awk '{print $2}' /proc/acpi/button/lid/LID0/state) 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 では画面が真っ黒になるだけでバックライトがオフにならないことがあります。公式リポジトリvbetool を使うことでこれは修正できます。LCD セクションを以下のように変更してください:

case $(awk '{print $2}' /proc/acpi/button/lid/LID0/state) 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
    }

この関数を使って、power ボタンが押された時に 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
    ;;

systemd を使用する新しいシステムでは、X11 のログインは必ずしも who では表示されないため、上記の getuser 関数は動作しません。代わりに loginctl を使用して必要な情報を取得します。例えば xuserrun を使います。

参照