Я пытаюсь автоматически запустить этот скрипт, каждый раз, когда я соединяюсь со своей гарнитурой Bluetooth.
Я создал файл/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"
но это ничего не делает. Условия прекрасны, простая тестовая команда инициирована, когда я ввожу это вместо этого. Сам сценарий также хорошо работает, когда выполнено вручную.
Что идет не так, как надо здесь?
Обновление: существует ошибка при запущении скрипта с sudo -u USER
(см. ниже для деталей). Это могло быть проблемой? И как делает sudo-луг к тем же вещам прерывания пользователем?
Обновление 2: После замены всех экземпляров pacmd
с pactl
в a2dp.py
(и замена 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.
Обновление 3 (Решение): измененный сценарий (pacmd-> pactl, посмотрите Обновление 2) с переменными среды DISPLAY=:0
и XAUTHORITY=/home/USER/.Xauthority
добился цели. Правило 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
Выполнение просто сценарий Python через udev:
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 __name__ == '__main__':
main()
снова создаст папку, когда устройство будет подключено.
Запущение скрипта от терминала с sudo -u USER
или даже sudo -u root
теперь работы, как предназначено (Для originial сценария это привело к:
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)
Изменить a2dp.py
путем замены всех экземпляров pacmd
с pactl
корректировка 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}"
Этот сценарий обертки выполняет следующее:
Это узнает $USER
при владении рабочим экземпляром pulseaudio, затем устанавливает переменные среды DISPLAY=:0
и XAUTHORITY=/home/$USER/.Xauthority
необходимый для pactl
работать. Это должно заставить его работать на всех пользователей на машине. (Я не протестировал эффекты многочисленных пользователей, зарегистрированных одновременно.)
Это проверяет, приостановлен ли соответствующий приемник и только затем работает a2dp_2.py
. Это необходимо для предотвращения бесконечного цикла, вызванного a2dp_2.py
повторное подключение устройства и таким образом инициирование правила.
Это работает a2dp_2.py
как $USER. Если выполнено как корень, a2dp_2.py
оставит pulseaudio и таким образом любые параметры звука, недоступные без полномочий пользователя root.
Альтернативное решение с помощью dbus цикла может быть найдено на странице sript разработчика.
Фиксация для исходной ошибки теперь доступна здесь и может быть легко установлена путем добавления 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
. Мы нашли три пути устройства. Одно соответствующее для нас /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}
.
Даже если вывод будет выглядеть полностью отличающимся, то эти две команды будут хорошим началом в поиске соответствующих условий для правила udev.
Правило:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="??:??:??:??:??:??" RUN+="/usr/local/bin/a2dp-wrapper.sh $attr{name}"
инициирует для любого устройства ввода данных, которое имеет атрибут имени, который похож на MAC-адрес, и условное выражение в сценарии обертки должно удостовериться, что никакие непреднамеренные меры не приняты.
У меня нет никакого другого аудиоустройства Bluetooth легко доступным для тестирования этого, но я вижу много потенциальных проблем:
Это будет только работать на bluetooth-устройство, которое распознано как устройство ввода данных, содержащее MAC-адрес в атрибуте имени. Не каждое устройство может быть распознано как таковое.
Это решение не очень изящно, поскольку правило будет инициировано для любого устройства ввода данных. Однако я не смог найти, что ясные индикаторы определяют аудиоустройство Bluetooth. (Как замечено выше, устройство ввода данных не имеет никаких дальнейших атрибутов, и bluetooth-устройство не показывает признака того, чтобы быть аудиоустройством, и при этом оно не содержит MAC-адрес. Возможно, ACPI был бы лучше для этого.)
Вы не можете хотеть рассматривать каждое аудиоустройство Bluetooth то же: можно хотеть использовать протокол HSP для гарнитуры, или Вы не можете хотеть автоматически переключаться на динамики своего соседа по дому, с которыми Вы соединились в какой-то момент, каждый раз, когда они доступны. В тех случаях, вероятно, предпочтительно иметь отдельное правило для каждого устройства.
Я буду продолжать обновлять это сообщение, поскольку я узнаю больше.