玩转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 连接的对象都自动支持,无需服务端显式实现。

扩展阅读

相关推荐
维克兜率天10 分钟前
【维克】指数调整:哪些股票会被“强制买入“?
人工智能·python·算法
罗西的思考1 小时前
【轻量化复刻大模型】线性注意力交互式演示
人工智能·算法·机器学习
神也畏惧菠萝1 小时前
Day08 Python流程控制从入门到上瘾:if/match/while/for四件套,从B站登录一路打到猜数字游戏
python·算法·数据存储·for·while·if·ifelse
揽星河..1 小时前
【C语言】分支和循环
c语言·c++·算法
AI_Lab012 小时前
宝塔用了两年,有没有必要换成轻量方案?
linux·运维·服务器
by209992 小时前
Linux GDB 调试与 CGDB 使用
linux·运维·服务器·经验分享
星恒随风2 小时前
Linux网络编程:应用层协议究竟是什么?从网络计算器到TCP Socket抽象基类完整实现
linux·网络·笔记·tcp/ip
Fuyo_11193 小时前
C++ AVL树保姆级详解:从平衡因子到四大旋转机制
java·c++·算法
jktantan3 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript