acpid (日本語)
関連記事
acpid2 は ACPI イベントを伝える、柔軟性と拡張性があるデーモンです。イベントが発生すると、そのイベントを処理するプログラムを実行します。イベントは以下のようなアクションによって引き起こされます:
- Power/Sleep/Suspend ボタンなど、特殊なキーを押す
- ノートパソコンのフタを閉じる
- ノートパソコンに AC 電源アダプタを接続 (切断) する
- イヤフォンジャックを接続 (切断) する
Contents
インストール
公式リポジトリの 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
サンプルイベント
以下は /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