Bluetoothヘッドセットに接続するたびに、自動的に this スクリプトを実行しようとしています。
ファイル/etc/udev/rules.d/80-bt-headset.rulesを次の行で作成しました
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" RUN+="/home/USER/.local/bin/a2dp.py 00:22:37:3D:DA:50"
しかし、それは何もしません。条件は問題ありません。代わりに入力すると、簡単なテストコマンドがトリガーされます。スクリプト自体は、手動で実行しても正常に機能します。
ここで何が問題になっていますか?
Update:Sudo -u USER
でスクリプトを実行するとエラーが発生します(詳細については以下を参照)。これが問題になりますか?そして、同じユーザーへのSudo-ingはどのように物事を壊しますか?
更新2:a2dp.py
のpacmd
のすべてのインスタンスをpactl
に置き換えた後(およびlist-sinks
をlist sinks
に置き換えて有効にするpactlコマンド)、Sudo -u USER
は動作しますが、udevルールはまだ動作しません。 /var/log/syslog
に次の行が表示されます
systemd-udevd[32629]: Process '/home/USER/.local/bin/a2dp_2.py 00:22:37:3D:DA:50' failed with exit code 1.
Update 3(Solution):環境変数DISPLAY=:0
およびXAUTHORITY=/home/USER/.Xauthority
を使用して修正されたskript(pacmd-> pactl、Update 2を参照)がトリックを行いました。 udevルール:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" ENV{DISPLAY}=":0" ENV{XAUTHORITY}="/home/USER/.Xauthority" RUN+="/home/USER/.local/bin/a2dp_2.py 00:22:37:3D:DA:50"
意図したとおりに機能しています。
(現在残っている唯一の問題は、ヘッドセットを再接続するときにスクリプト自体がルールをトリガーし、無限ループが発生することです。しかし、それは別の質問であり、回避策を見つけるのはそれほど難しくないはずです。実際、私はこのスレッドを開始したときにその動作を期待していました。)
条件は問題ありません:行:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" RUN+="/bin/mkdir /tmp/testme"
ヘッドセットに接続すると、新しいディレクトリが作成されます。
スクリプトa2dp.py自体は、ターミナルから
/home/USER/.local/bin/a2dp.py 00:22:37:3D:DA:50
Udevを介して単にPythonスクリプトを実行する:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" RUN+="/home/USER/.local/bin/atestscript.py"
atestscript.pyの内容は次のとおりです。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import subprocess
def main():
subprocess.Popen(['mkdir', '/tmp/atestdir'])
if __== '__main__':
main()
デバイスが接続されると、フォルダーが再び作成されます。
Sudo -u USER
またはSudo -u root
を使用して端末からスクリプトを実行すると、意図したとおりに動作するようになりました(元のスクリプトの場合:
USER@MACHINE:~$ Sudo -u USER /usr/local/bin/a2dp.py 00:22:37:3D:DA:50
Connection MADE
Device MAC: 00:22:37:3D:DA:50
Command: pacmd list-sinks failed with status: 1
stderr: No PulseAudio daemon running, or not running as session daemon.
Exiting bluetoothctl
上記のように、またはRUN+=
部分として以下の行のいずれかを使用してスクリプトを実行します。
/usr/bin/Sudo -u USER /usr/bin/python3 /home/USER/.local/bin/a2dp.py 00:22:37:3D:DA:50
/usr/bin/Sudo -u USER /home/USER/.local/bin/a2dp.py 00:22:37:3D:DA:50
/usr/bin/python3.5 /usr/local/bin/a2dp.py 00:22:37:3D:DA:50
ENV{DISPLAY}=":0" RUN+="/usr/local/bin/a2dp.py 00:22:37:3D:DA:50"
変更されたスクリプトでも機能しません。
ENV{DISPLAY}=":0" ENV{Pulse_RUNTIME_PATH}="/run/user/1000/Pulse/" RUN+="Sudo -u USER /home/USER/.local/bin/a2dp_2.py 00:22:37:3D:DA:50"
詳細情報:udevadmは、ヘッドセットへの接続時の出力を監視します:
KERNEL[104388.664737] add /devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/bluetooth/hci0/hci0:256 (bluetooth)
UDEV [104388.667185] add /devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/bluetooth/hci0/hci0:256 (bluetooth)
KERNEL[104390.848157] add /devices/virtual/input/input46 (input)
UDEV [104390.849150] add /devices/virtual/input/input46 (input)
KERNEL[104390.849471] add /devices/virtual/input/input46/event17 (input)
UDEV [104390.864692] add /devices/virtual/input/input46/event17 (input)
pacmd
のすべてのインスタンスをpactl
に置き換えてa2dp.py
を変更し、pacmd list-sinks
をpactl list sinks
に調整します(この場合、/usr/local/bin/a2dp_2.sh
として保存します)。
ラッパースクリプトを作成する/usr/local/bin/a2dp-wrapper.sh
#!/bin/bash
MAC=$1
MACMOD=$(echo $MAC | sed 's/:/_/g')
PID=$(pgrep pulseaudio)
USER=$(grep -z USER= /proc/$PID/environ | sed 's/.*=//')
export DISPLAY=:0
export XAUTHORITY=/home/$USER/.Xauthority
if pactl list sinks short | grep "bluez_sink\.$MACMOD.*SUSPENDED"
then
Sudo -u $USER /usr/local/bin/a2dp_2.py $MAC
fi
次の行を/etc/udev/rules.d/80-bt-headset.rules
に追加します。
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" RUN+="/usr/local/bin/a2dp-wrapper.sh $attr{name}"
このラッパースクリプトは、次のことを実現します。
Pulseaudioの実行中のインスタンスを所有している$USER
を見つけ、pactl
が機能するために必要な環境変数DISPLAY=:0
およびXAUTHORITY=/home/$USER/.Xauthority
を設定します。これにより、マシン上のすべてのユーザーに対して機能するはずです。 (複数のユーザーが同時にログインした場合の効果はテストしていません。)
対応するシンクが中断されているかどうかを確認してから、a2dp_2.py
を実行します。これは、デバイスを再接続してルールをトリガーするa2dp_2.py
によって引き起こされる無限ループを防ぐために必要です。
それは、a2dp_2.py
を$ USERとして実行します。ルートとして実行した場合、a2dp_2.py
は、ルート権限なしではアクセスできないパルスオーディオ、したがってオーディオ設定を残します。
Dbusループを使用する代替ソリューションは、 sript開発者のページ にあります。
元のバグの修正が利用可能になりました here 。ppa:ubuntu-audio-dev/Pulse-testing
を追加して利用可能なパッケージを更新することで簡単にインストールできます。
厳密には元の問題の一部ではありませんが、これは将来の参照に役立つ場合があります。デバイスのMACアドレスを見つける方法は多数あります。以下は、udevルールに最も役立つと思うものです。
udevadm monitor
を実行してデバイスを接続し、デバイスのパスを見つけます。出力は次のようになります。
USER@MACHINE:~$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
KERNEL[123043.617276] add /devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/bluetooth/hci0/hci0:256 (bluetooth)
UDEV [123043.647291] add /devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/bluetooth/hci0/hci0:256 (bluetooth)
KERNEL[123044.153776] add /devices/virtual/input/input68 (input)
KERNEL[123044.153911] add /devices/virtual/input/input68/event17 (input)
UDEV [123044.193415] add /devices/virtual/input/input68 (input)
UDEV [123044.213213] add /devices/virtual/input/input68/event17 (input)
Ctrl+C
でモニターを停止します。 3つのデバイスパスが見つかりました。関連するのは/devices/virtual/input/input68
です。
取得したパスをudevadm info
に差し込みます:
USER@MACHINE:~$ udevadm info -a -p /devices/virtual/input/input68
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/virtual/input/input68':
KERNEL=="input68"
SUBSYSTEM=="input"
DRIVER==""
ATTR{name}=="00:22:37:3D:DA:50"
ATTR{phys}==""
ATTR{properties}=="0"
ATTR{uniq}==""
MACアドレスは00:22:37:3D:DA:50
であり、ATTR{name}
として保存されていることもわかります。
出力が完全に異なって見える場合でも、これらの2つのコマンドは、udevルールに関連する条件を探すための良い出発点になります。
ルール:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="??:??:??:??:??:??" RUN+="/usr/local/bin/a2dp-wrapper.sh $attr{name}"
mACアドレスのように見える名前属性を持つ入力デバイスに対してトリガーされます。ラッパースクリプトの条件は、意図しないアクションが行われないことを確認する必要があります。
これをテストするためのBluetoothオーディオデバイスは他にありませんが、いくつかの潜在的な問題があります。
これは、name属性にMACアドレスを含む入力デバイスとして認識されるbluetoothデバイスでのみ機能します。すべてのデバイスがそのように認識されるとは限りません。
このソリューションは、入力デバイスに対してルールがトリガーされるため、あまりエレガントではありません。ただし、Bluetoothオーディオデバイスを識別するための明確なインジケーターを見つけることができませんでした。 (上記のように、入力デバイスにはそれ以上の属性はなく、bluetoothデバイスにはオーディオデバイスであることの表示はなく、MACアドレスも含まれていません。おそらくACPIの方が良いでしょう。)
すべてのBluetoothオーディオデバイスを同じように扱いたくない場合があります:ヘッドセットにHSPプロトコルを使用したい場合や、ハウスメイトのスピーカーに自動的に切り替えたくない場合があります。利用できます。そのような場合、おそらく各デバイスに個別のルールを設定することが望ましいでしょう。
詳細については、この投稿を更新し続けます。