acpid (日本語) - ArchWiki

# acpid (日本語)

関連記事

- ACPI モジュール
- DSDT

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

- Power/Sleep/Suspend ボタンなど、特殊なキーを押す
- ノートパソコンのフタを閉じる
- ノートパソコンに AC 電源アダプタを接続 (切断) する
- イヤフォンジャックを接続 (切断) する

Note: 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

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

    power/button PBTN 00000000 00000b31

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

    $1 power/button
    $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

Tip: 以下に記載している、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

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

ボリュームボタンの 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

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

ボリュームコントロールと同じように、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.sh` の button/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 を使います。

### ACPI ホットキー

ACPI イベントを受け止めるのに、直接 `/etc/acpi/handler.sh` を編集する他に、別のシェルスクリプトを指定することもできます (`/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 から返されてきた応答です。

また、exailectl スクリプトは Exaile 音楽プレイヤーをコントロールするための簡単なシェルスクリプトです。ACPID は root で実行されるため、次を使う必要があります:

    $ sudo -u username exaile

これをしていないと、ユーザーレベルのプログラムを検出されずに別のものが再作成されます。

## 参照

- http://acpid.sourceforge.net/ - acpid ホームページ
- http://www.gentoo-wiki.info/ACPI/Configuration - Gentoo wiki

Category:

- Power management (日本語)