Python 通过tcp连接到dbus

Python 通过tcp连接到dbus,python,dbus,Python,Dbus,我编写了一个简单的python程序来播放和暂停女妖音乐播放器。 当它在我自己的机器上工作时,我很难在连接到同一路由器(LAN)的远程计算机上工作。 我编辑了远程机器的session.conf,添加了这一行: <listen>tcp:host=localhost,port=12434</listen> 这就是我尝试执行它时得到的结果 Traceback (most recent call last): File "dbus3.py", line 4, in <m

我编写了一个简单的python程序来播放和暂停女妖音乐播放器。 当它在我自己的机器上工作时,我很难在连接到同一路由器(LAN)的远程计算机上工作。 我编辑了远程机器的session.conf,添加了这一行:

<listen>tcp:host=localhost,port=12434</listen>
这就是我尝试执行它时得到的结果

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
因此,当我按ctrl+alt+f1组合键时,将session.conf更改为原始状态并重新启动,它将正常引导

这是怎么回事?
如何让dbus守护进程侦听tcp连接而不遇到问题?

我最近需要设置它,并发现诀窍是:为
会话.conf中的
元素排序。您应该确保TCP元素首先出现。我知道这很奇怪,但至少对我来说是真的。(如果我颠倒顺序,将UNIX套接字
元素放在第一位,我会看到完全相同的黑屏行为。)

此外,预先添加TCP
标记是必要的,但还不够。要通过TCP实现远程D总线连接,您需要做三件事:

  • 在UNIX标签上方添加一个
    标签,如下所示:

    <listen>tcp:host=localhost,bind=*,port=55556,family=ipv4</listen>
    <listen>unix:tmpdir=/tmp</listen>
    
    完成这三件事后,您应该能够远程连接到会话总线。以下是在中指定远程连接时的外观:

    请注意,如果您也想连接到系统总线,则需要对
    /etc/dbus-1/system.conf
    进行类似的更改,但需要指定不同的TCP端口,例如55557。(奇怪的是,在这种情况下,元素顺序似乎并不重要。)

    在这种配置中,我注意到的唯一奇怪的行为是,运行带有
    sudo
    (例如,
    sudo gvim
    )的桌面应用程序会产生错误或直接失败,并说“没有运行D-BUS守护进程”。但这是我很少需要做的事情,几乎不重要

    如果要使用
    dbus send
    发送到远程机器,则需要相应地设置
    dbus\u SESSION\u BUS\u ADDRESS
    ,例如:

    export DBUS_SESSION_BUS_ADDRESS=tcp:host=localhost,bind=*,port=55556,family=ipv4
    
    即使要发送到的总线实际上是远程机器的系统总线,只要设置与目标上的TCP
    /etc/dbus-1/system.conf
    中的TCP
    标记相匹配,该功能也可以工作。(多亏了这个提示。直到我偶然发现了他的答案,我才相信
    dbus-send
    支持远程操作。)

    更新:如果您正在使用systemd(并且想要访问系统总线),您可能还需要在
    /lib/systemd/system/dbus.socket
    中添加一行,说明
    ListenStream=5555557
    ,如下所示:

    [Socket]
    ListenStream=/var/run/dbus/system_bus_socket
    ListenStream=55557  # <-- Add this line
    
    [Socket]
    ListenStream=/var/run/dbus/system\u总线\u套接字
    ListenStream=55557#自dbus 1.6.12(例如kubuntu 13.10)以来,您的连接也将被拒绝,除非您添加到dbus配置文件(或/etc/dbus-1/mybus.conf或需要远程访问的接口,即system.d/my.interface.conf)


    另一个感谢@Shorin,另一个仅供参考-我必须这样做才能让我的工作:

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

    您必须看到类似于
    0.0.0.0:55884
    的内容,而不是类似于
    0 127.0.0.1:55884
    的默认内容(ubuntu)。对不起,我对网络几乎一无所知,我应该配置iptable以允许连接吗?我认为iptable可以通过默认的有用网络命令实现一切:
    netstat-na
    lsof-ni
    tcpdump-n-I eth0
    iptables-nvL
    。我认为结合使用这些方法可以告诉你,你的过程是否在倾听,如果是的,它是否被某种方式阻止了。祝你好运您可以使用
    socat
    将tcp数据包转发到本地unix套接字,这样您就不需要重新启动dbus守护进程。另外,请尝试tcp:host=0.0.0.0,port=12434
    ——这将把侦听套接字绑定到所有接口。(检查重启后它是否真的在监听-
    telnet 192.168.1.7 12434
    仅供参考,我需要这样的东西才能工作(注意家族的绑定和设置):tcp:host=localhost,bind=*,port=55884,family=ipv4谢谢,@Shorin。我更新了我的答案,以包含
    bind
    family
    键/值对。我认为并非所有情况下都需要它们(我的答案中没有),并且这些值可能需要针对不同的系统进行调整,但包含它们可能会使答案更完整,对其他人更有帮助。:-)顺便说一句,我在Android设备上尝试了这一点。它在重新启动时挂起。需要闪存才能重新工作。如果您正在努力使dbus在Microsoft的Windows linux子系统上运行,这个答案实际上会有所帮助。@TusharVazirani:您可以使用
    dbus_SESSION_BUS_ADDRESS
    环境变量来指定远程目标,即。,使用类似于
    DBUS\u SESSION\u BUS\u ADDRESS=tcp:host=192.168.1.17,bind=*,port=55556,family=ipv4./my\u python\u app.py
    的方法运行它。(注意:正如我在回答中所提到的,即使您连接的总线实际上是远程机器的系统总线,只要其
    system.conf
    配置为允许通过TCP进行连接,这也可以工作。)
    <auth>ANONYMOUS</auth>
    
    <allow_anonymous/>
    
    <listen>tcp:host=localhost,bind=*,port=55556,family=ipv4</listen>
    <listen>unix:tmpdir=/tmp</listen>
    
    <auth>ANONYMOUS</auth>
    <allow_anonymous/>
    
    export DBUS_SESSION_BUS_ADDRESS=tcp:host=localhost,bind=*,port=55556,family=ipv4
    
    [Socket]
    ListenStream=/var/run/dbus/system_bus_socket
    ListenStream=55557  # <-- Add this line
    
    <apparmor mode="disabled"/>
    
    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")
    
    <listen>tcp:host=localhost,bind=0.0.0.0,port=55884</listen>
    
    netstat -plntu | grep 55884
    
    tcp   0     0 0.0.0.0:55884    0.0.0.0:*     LISTEN    707/dbus-daemon