Подключение к dbus через TCP

Я написал простую программу на Python для воспроизведения и приостановки музыкального плеера банши. Хотя он работает на моей собственной машине, у меня возникают проблемы с удаленным компьютером, подключенным к тому же маршрутизатору (LAN). Я отредактировал файл session.conf удаленной машины, добавив следующую строку:

<listen>tcp:host=localhost,port=12434</listen>

и вот моя программа:

    import dbus


    bus_obj=dbus.bus.BusConnection("tcp:host=localhost,port=12434")
    proxy_object=bus_obj.get_object('org.bansheeproject.Banshee',                              
    '/org/bansheeproject/Banshee/PlayerEngine')

    playerengine_iface=dbus.Interface(proxy_object,
    dbus_interface='org.bansheeproject.Banshee.PlayerEngine')

    var=0

    while (var!="3"):
        var=raw_input("\nPress\n1 to play\n2 to pause\n3 to exit\n")


            if var=="1":
                print "playing..."
                playerengine_iface.Play()

            elif var=="2":
                print "pausing"
                playerengine_iface.Pause()

Это то, что я получаю, когда пытаюсь это выполнить

Traceback (most recent call last):
  File "dbus3.py", line 4, in <module>
    bus_obj=dbus.bus.BusConnection("tcp:host=localhost,port=12434")
  File "/usr/lib/python2.7/dist-packages/dbus/bus.py", line 125, in __new__
    bus = cls._new_for_bus(address_or_type, mainloop=mainloop)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.NoServer: Failed to connect to socket "localhost:12434" Connection refused

Что я здесь не так делаю? я должен отредактировать /usr/lib/python2.7/dist-packages/dbus/bus.py

ОБНОВИТЬ:

хорошо, вот сделка, когда я добавлю

<listen>tcp:host=192.168.1.7,port=12434</listen>

в /etc/dbus-1/session.conf, затем перезагрузите компьютер, надеясь, что он начнет слушать при перезагрузке, он никогда не загружается. Он застревает на экране загрузки и иногда мигает черный экран со следующим текстом:

Pulseaudio Configured For Per-user Sessions Saned Disabled;edit/etc/default/saned

поэтому, когда я иду ctrl+alt+f1, меняю session.conf в исходное состояние и перезагружаюсь, он загружается правильно.

О чем все это? Как сделать так, чтобы dbus daemon прослушивал tcp-соединения, не сталкиваясь с проблемами?

3 ответа

Решение

Недавно мне нужно было настроить это, и обнаружил, что хитрость заключается в следующем: порядок имеет значение для <listen> элементы в session.conf, Вы должны убедиться, что элемент TCP появляется первым. Странно, я знаю, но это правда, по крайней мере, для моего случая. (Я вижу точно такое же поведение черного экрана, если я поменяю порядок и вставлю сокет UNIX <listen> элемент первый.)

Кроме того, предваряя TCP <listen> тег необходим, но не достаточен. Чтобы сделать удаленные соединения D-Bus через TCP, вам нужно сделать три вещи:

  1. Добавить <listen> тег над UNIX, похожий на этот:

    <listen>tcp:host=localhost,bind=*,port=55556,family=ipv4</listen>
    <listen>unix:tmpdir=/tmp</listen>
    
  2. Добавьте строку (прямо под <listen> теги в порядке), что говорит:

    <auth>ANONYMOUS</auth>
    
  3. Добавьте еще одну строку под ними, которая говорит:

    <allow_anonymous/>
    

<auth> тег должен быть добавлен в дополнение к любому другому <auth> теги, которые могут содержаться в вашем session.conf, В итоге ваш session.conf должен содержать фрагмент, который выглядит следующим образом:

<listen>tcp:host=localhost,bind=*,port=55556,family=ipv4</listen>
<listen>unix:tmpdir=/tmp</listen>

<auth>ANONYMOUS</auth>
<allow_anonymous/>

Выполнив эти три вещи, вы сможете удаленно подключиться к сеансовой шине. Вот как это выглядит при указании удаленного соединения в D-Feet:

Захват экрана D-Feet

Обратите внимание, что если вы хотите подключиться и к системной шине, вам необходимо внести аналогичные изменения в /etc/dbus-1/system.conf, но укажите другой порт TCP, например, 55557. (Как ни странно, порядок элементов в данном случае не имеет значения.)

Единственное странное поведение, которое я заметил в этой конфигурации, заключается в том, что приложения для настольных ПК работают с sudo (например, sudo gvim) имеет тенденцию генерировать ошибки или сразу завершаться с ошибкой, говоря: "Не работает демон D-BUS". Но это то, что мне нужно делать так редко, что это вряд ли имеет значение.

Если вы хотите отправить на удаленный компьютер с помощью dbus-sendнужно установить DBUS_SESSION_BUS_ADDRESS соответственно, например, что-то вроде:

export DBUS_SESSION_BUS_ADDRESS=tcp:host=localhost,bind=*,port=55556,family=ipv4

Это работает, даже если шина, которую вы хотите отправить, на самом деле является системной шиной удаленного компьютера, если настройка соответствует TCP <listen> отметить в /etc/dbus-1/system.conf на цель. (Спасибо Martin Vidner за этот совет. Пока я не наткнулся на его ответ на этот вопрос, я не верил dbus-send поддерживается удаленное управление.)

ОБНОВЛЕНИЕ: Если вы используете systemd (и хотите получить доступ к системной шине), вам также может понадобиться добавить строку с надписью ListenStream=55557 в /lib/systemd/system/dbus.socket, вот так:

[Socket]
ListenStream=/var/run/dbus/system_bus_socket
ListenStream=55557  # <-- Add this line

ОБНОВЛЕНИЕ 2: Спасибо @altagir за то, что он указал, что последние версии D-Bus позволят использовать посредничество AppArmor в системах, где он доступен, поэтому вам также может понадобиться добавить <apparmor mode="disabled"/> в session.conf/system.conf чтобы эти инструкции работали.

Начиная с dbus 1.6.12 (например, kubuntu 13.10), ваше соединение также будет отклонено, если вы не добавите его в файл конфигурации dbus (либо / etc / dbus-1 / mybus.conf, либо интерфейс, требующий удаленного доступа, например, system.d / my. interface.conf)

<apparmor mode="disabled"/>

ОБНОВЛЕНИЕ: После попытки создать профиль apparmor, позволяющий службе подключаться к пользовательскому демону dbus, кажется, что соединение всегда отклоняется из-за ошибки в DBUS... Поэтому сейчас мы ДОЛЖНЫ отключать apparmor всякий раз, когда вы используете tcp=... Исправлена ​​ошибка на 14.04

Я открыл ошибку на bugs.launchpad.net после обсуждения с Тайлером Хиксом:

Посреднический код AppArmor имеет возможность проверять метки пиров только через доменные сокеты UNIX. Скорее всего, при получении метки возникает ошибка, а затем происходит отказ в соединении.

Примечание: флаг отключения не распознается dbus < 1.6.12, поэтому вам нужно упаковать разные версии mydaemon.conf в зависимости от systen), иначе dbus-daemon не запустится при запуске, если нет apparmor... Я использовал сейчас в мой CMakeLists.txt:

IF(EXISTS "/usr/sbin/apparmor_status")
  install(FILES dbus_daemon-apparmordisabled.conf RENAME dbus_daemon.conf DESTINATION /etc/dbus-1/ )
ELSE (EXISTS "/usr/sbin/apparmor_status")
   install(FILES dbus_daemon.conf DESTINATION /etc/dbus-1/ )
ENDIF(EXISTS "/usr/sbin/apparmor_status")

Еще одно спасибо @Shorin, и еще одно FYI - я должен был сделать что-то вроде этого, чтобы моя работа:

<listen>tcp:host=localhost,bind=0.0.0.0,port=55884</listen>

Обратите внимание bind=0.0.0.0 - bind=* не работал для меня, и я оставил family=ipv4 часть. Я на Ubuntu 12.04. Я использовал netstat на удаленной машине, чтобы подтвердить, что dbus прослушивает порт, и telnet из локальной сети, чтобы подтвердить, что порт открыт.

netstat -plntu | grep 55884

tcp   0     0 0.0.0.0:55884    0.0.0.0:*     LISTEN    707/dbus-daemon

Вы должны увидеть что-то вроде 0 0.0.0.0:55884 а не как то 0 127.0.0.1:55884,

Другие вопросы по тегам