玩转DBus命令行工具之gdbus使用

gdbus 使用指南

概述

gdbus 是 GLib 提供的 D-Bus 工具集,功能比 dbus-send 更强大,支持复杂类型(variant、数组等),自动显示返回值,提供更好的类型处理。

基本语法

调用方法

bash 复制代码
gdbus call [--system|--session] \
  --dest=服务名 \
  --object-path=对象路径 \
  --method=接口名.方法名 [参数...]

内省对象

bash 复制代码
gdbus introspect [--system|--session] \
  --dest=服务名 \
  --object-path=对象路径

监听信号

bash 复制代码
gdbus monitor [--system|--session] \
  --dest=服务名 \
  --object-path=对象路径

方法调用

无参数方法调用

bash 复制代码
gdbus call --session \
  --dest=org.freedesktop.DBus \
  --object-path=/org/freedesktop/DBus \
  --method=org.freedesktop.DBus.ListNames

带参数的方法调用

bash 复制代码
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=com.example.Interface.GetData "parameter"

多个参数

bash 复制代码
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=com.example.Interface.SetData "param1" "param2" 123

访问属性

属性访问通过 org.freedesktop.DBus.Properties 接口实现。

重要说明org.freedesktop.DBus.Properties 接口需要服务端实现支持。如果服务端未实现此接口,调用会失败。

获取属性

bash 复制代码
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=org.freedesktop.DBus.Properties.Get \
  "com.example.Interface" "PropertyName"

设置属性

bash 复制代码
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=org.freedesktop.DBus.Properties.Set \
  "com.example.Interface" "PropertyName" "<'new value'>"

注意 :设置属性时,值需要用 <> 包裹,字符串用单引号。

获取所有属性

bash 复制代码
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=org.freedesktop.DBus.Properties.GetAll \
  "com.example.Interface"

内省对象

bash 复制代码
# 内省对象
gdbus introspect --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object

重要说明org.freedesktop.DBus.Introspectable 接口需要服务端实现支持。如果服务端未实现此接口,调用会失败。此接口允许客户端动态发现对象的接口、方法、信号和属性等信息。

输出示例

复制代码
node /com/example/Object {
  interface com.example.Interface {
    methods:
      GetData(out s result);
      Echo(in  s input,
           out s output);
    signals:
      DataChanged(s data);
    properties:
      @org.freedesktop.DBus.Property.EmitsChangedSignal = 'false'
      readwrite s Data = 'default value';
  };
  interface org.freedesktop.DBus.Properties {
    methods:
      Get(in  s interface_name,
          in  s property_name,
          out v value);
      Set(in  s interface_name,
          in  s property_name,
          in  v value);
      GetAll(in  s interface_name,
             out a{sv} properties);
    signals:
      PropertiesChanged(s interface_name,
                        a{sv} changed_properties,
                        as invalidated_properties);
  };
  interface org.freedesktop.DBus.Introspectable {
    methods:
      Introspect(out s xml_data);
  };
};

注意gdbus introspect 的输出格式是易读的文本格式,而不是 XML。如果需要 XML 格式,可以使用 dbus-send 调用 Introspect 方法。

监听信号

bash 复制代码
# 监听信号
gdbus monitor --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object

类型处理

variant 类型

gdbus 对 variant 类型有更好的支持:

bash 复制代码
# 设置 variant 类型的属性
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=org.freedesktop.DBus.Properties.Set \
  "com.example.Interface" "VariantProperty" "<123>"

数组类型

bash 复制代码
# 传递数组参数
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=com.example.Interface.ProcessArray \
  "['item1', 'item2', 'item3']"

字典类型

bash 复制代码
# 传递字典参数
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=com.example.Interface.ProcessDict \
  "{'key1': 'value1', 'key2': 'value2'}"

实际应用示例

示例 1:获取服务属性

bash 复制代码
# 获取 D-Bus 服务的特性列表(示例:使用 org.freedesktop.DBus 服务)
gdbus call --session \
  --dest=org.freedesktop.DBus \
  --object-path=/org/freedesktop/DBus \
  --method=org.freedesktop.DBus.Properties.Get \
  "org.freedesktop.DBus" "Features"

# 注意:如果系统中有 MPRIS 媒体播放器运行,可以使用以下命令获取播放状态:
# gdbus call --session \
#   --dest=org.mpris.MediaPlayer2.vlc \
#   --object-path=/org/mpris/MediaPlayer2 \
#   --method=org.freedesktop.DBus.Properties.Get \
#   "org.mpris.MediaPlayer2.Player" "PlaybackStatus"

示例 2:查询系统服务信息

bash 复制代码
# 获取 D-Bus 服务的接口列表
gdbus call --session \
  --dest=org.freedesktop.DBus \
  --object-path=/org/freedesktop/DBus \
  --method=org.freedesktop.DBus.Properties.Get \
  "org.freedesktop.DBus" "Interfaces"

# 注意:如果系统中有 UPower 服务运行,可以使用以下命令获取电池信息:
# gdbus call --system \
#   --dest=org.freedesktop.UPower \
#   --object-path=/org/freedesktop/UPower/devices/battery_BAT0 \
#   --method=org.freedesktop.DBus.Properties.Get \
#   "org.freedesktop.UPower.Device" "Percentage"

示例 3:查看对象树

bash 复制代码
# 使用 ObjectManager 查看所有对象
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/ \
  --method=org.freedesktop.DBus.ObjectManager.GetManagedObjects

重要说明org.freedesktop.DBus.ObjectManager 接口需要服务端实现支持。通常由服务在根对象路径(如 /)上实现。

示例 4:检查服务连接

bash 复制代码
# 使用 Peer.Ping 测试服务是否可用
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=org.freedesktop.DBus.Peer.Ping

返回值说明

  • 如果服务可用,返回 ()(空括号),表示方法调用成功,但 Ping 方法没有返回值
  • 如果服务不可用,返回错误:Error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown

判断连接成功 :返回 () 表示连接成功;返回错误信息表示服务不存在或不可用。

bash 复制代码
# 获取机器ID
gdbus call --session \
  --dest=com.example.Service \
  --object-path=/com/example/Object \
  --method=org.freedesktop.DBus.Peer.GetMachineId

返回值说明 :返回机器的唯一标识符(UUID 格式),例如:('550e8400-e29b-41d4-a716-446655440000',)

重要说明org.freedesktop.DBus.Peer 接口由 D-Bus 库自动提供,不需要服务端显式实现。所有通过 D-Bus 连接的对象都自动支持此接口。

常用选项

  • --system:使用系统总线
  • --session:使用会话总线(默认)
  • --dest=服务名:指定目标服务
  • --object-path=路径:指定对象路径
  • --method=接口.方法:指定方法名

gdbus 的优势

  1. 自动显示返回值 :不需要 --print-reply 参数
  2. 更好的类型处理:支持 variant、数组、字典等复杂类型
  3. 更清晰的输出:返回值格式更易读
  4. 内省功能 :提供 introspect 子命令
  5. 信号监听 :提供 monitor 子命令

与 dbus-send 的对比

特性 dbus-send gdbus
返回值显示 需要 --print-reply 自动显示
variant 支持 有限 完整支持
复杂类型 支持有限 完整支持
内省 需要手动调用方法 提供 introspect 子命令
信号监听 不支持 提供 monitor 子命令

注意事项

  1. 依赖:需要 GLib 库支持
  2. 参数格式 :variant 类型需要用 <> 包裹
  3. 字符串参数:字符串参数用单引号包裹
  4. 权限:系统总线操作通常需要 root 权限
  5. 标准接口支持
    • 需要服务端实现的标准接口

      • org.freedesktop.DBus.Properties:属性访问接口(Get、Set、GetAll)
      • org.freedesktop.DBus.Introspectable:内省接口(Introspect)
      • org.freedesktop.DBus.ObjectManager:对象管理接口(GetManagedObjects)

      如果服务端未实现这些接口,相应的调用会失败并返回错误。客户端在调用前应检查服务是否支持所需接口。

    • 自动提供的标准接口

      • org.freedesktop.DBus.Peer:对等接口(Ping、GetMachineId)

      此接口由 D-Bus 库自动提供,所有通过 D-Bus 连接的对象都自动支持,无需服务端显式实现。

扩展阅读

相关推荐
二狗哈2 小时前
Cesium快速入门34:3dTile高级样式设置
前端·javascript·算法·3d·webgl·cesium·地图可视化
QT 小鲜肉2 小时前
【Linux命令大全】001.文件管理之mdir命令(实操篇)
linux·运维·服务器·chrome·笔记
@卞2 小时前
排序算法(2)--- 选择排序
算法·排序算法
脏脏a2 小时前
链式存储范式下的二叉树:基础操作实现解析
c语言·数据结构·算法·二叉树
iAkuya2 小时前
(leetcode)力扣100 26环状链表2(双指针)
算法·leetcode·链表
sin_hielo2 小时前
leetcode 2402(双堆模拟,小根堆)
数据结构·算法·leetcode
大聪明-PLUS2 小时前
企鹅网:Linux 网络
linux·嵌入式·arm·smarc
weixin_461769402 小时前
3. 无重复字符的最长子串
c++·算法·滑动窗口·最长字串
Morwit2 小时前
【力扣hot100】 312. 戳气球(区间dp)
c++·算法·leetcode