D-Bus 基本工具與實用指令教學:busctl、dbus-monitor、dbus-send 使用指南

更新 發佈閱讀 15 分鐘

D-Bus 基本工具

  • busctlsystemd 提供的 D-Bus 的raw command,功能強大, 是我最常使用。
  • dbus-monitor:專門用來監看 Bus 上所有訊息的即時狀態, 曾經想用他看bus上的signal有沒有正確收送。(但我自己的經驗是, 在多services運行的系統中, 而且每個service都非常忙碌的狀態下, 整體觀察下來獲取的信息太多, 結果找不到重點想看的部分。至今我也沒找到他更好的用法…如果大家有玩出什麼好方法, 歡迎再跟我分享。)
  • dbus-send:傳統的 D-Bus 命令列工具, 單一行為觸發測試的時候會用到。

實用指令

因為我目前沒有server可以跑, 所以example的部分的大家參考就好, 有些可能是以前抓的, 有些可能是ubuntu的, 有些可能是網路上看到覺得這個指令也不錯的。建議大家使用指令這件事情就是親自找個virtual machine或者有真實系統的, 就在系統上跑跑看。 busctl的版本不一樣, 你可能會看到不一樣的結果。那…要怎麼知道我現在手上的busctl有哪些subcommand可以執行呢?我看了一下systemd source code src/busctl/busctl.c 不要太舊的版本都有 help() 所以理論上是可以執行busctl --help

那接下來, 就是可以跟著來下幾個指令玩玩:

  • 列出所有服務 (Bus Names):busctl --system list 範例輸出:
    NAME                                PID PROCESS         CONNECTION
    :1.0 512 systemd-logind ...
    org.freedesktop.DBus - - -
    org.freedesktop.NetworkManager 890 NetworkManager ...

    org.freedesktop.DBus 服務。它的 PID 和 PROCESS 欄位是空的,因為它就是 D-Bus Daemon 本身,是整個D-Bus的管理者。
    • 查詢某service的object tree:busctl --system tree org.freedesktop.NetworkManager
    • 即時監聽廣播 (Signals):dbus-monitor --system "type='signal'"
      Note:當你插拔網路線或改變 Wi-Fi 狀態,會看到 signal 訊息跳出來。試著解析訊息中的 sender (發送者)、interface (介面名稱) 和 member (訊號名稱)。

詳細的使用說明, 請餐考:
https://www.freedesktop.org/software/systemd/man/latest/busctl.html 官方文件。

核心功能:Method, Property, Signal

  • Method Call:就像「一封信 + 回信」。它是主動的請求,通常會得到一個回覆(無論是成功或失敗)。這邊針對系統的設計, 有一件重要的事情:Method Call 可以是同步的(程式停下來等待回覆);也可以是非同步的(程式繼續執行,稍後再處理回覆)。
  • Property:像「隨時可查的公告」。它代表一個物件的狀態。你可以讀取它(get),也可以在有權限的情況下修改它(set)。
  • Signal:像「郵局廣播」。它是事件驅動的,通常沒有回覆。服務發出一個 Signal,所有感興趣的客戶端都能收到。
  • Interface:像是部門的「契約」或「規格書」,定義了這個部門(物件)能提供哪些 MethodPropertySignal

D-Bus Signature

在 D-Bus 裡,程式之間要互相傳遞資料。問題來了, 傳的東西是字串?整數?布林?還是陣列? 收的人要怎麼知道怎麼解讀?

Signature 就是「型別說明書」。它用簡單的字母縮寫,告訴你「這個參數是什麼型別」。

常用的Signature:

raw-image

進階容器型別:

  • aT → 陣列(array of T)
    • 例如 as = 字串陣列 = ["Taipei","Oxford","Florence"]
  • (…) → 結構(多個值打包)
    • 例如 (si) = 一個字串(假設代表姓名) + 一個整數(假設代表幸運數字)
      busctl --user call org.citybonnie.Hello /org/citybonnie/Hello \\
      org.citybonnie.Hello RegisterUser '(si)' "Bonnie" 87
  • a{KT} → 字典(map)
    • 例如 a{ss} = 字串對字串的對照表
    • 以下的指令是表示有兩組, 每組都是兩個字串組成
      busctl --user call org.citybonnie.Hello /org/citybonnie/Hello \\
      org.citybonnie.Hello UpdateConfig a{ss} 2 \\
      "city" "Florence" \\
      "mood" "curious"
  • v → variant (裡面包一個型別 + 值)
    • 例如你希望包的是一個整數, 那就要在v後面接i然後一個整數值, 那指令可能是:
      busctl --user call org.citybonnie.Hello /org/citybonnie/Hello \\
      org.citybonnie.Hello EchoVariant v i 123
    • 例如你希望包的是一個字串, 那你的指令可能是:

練習時間

下面有一個daemon, 也不知到能不能work, 也不知道執行起來長怎樣?

如果你的環境還沒有安裝相關套件的話可以安排一下:

$ sudo apt-get update $ sudo apt-get install -y python3-dbus python3-gi gir1.2-glib-2.0

接著, 把這個daemon執行起來之後, 你就可以用busctl來了解一下這個daemon究竟實作了怎樣的method, property and signal?

PS. 這裡用的是session bus, 所以要用busctl --user / dbus-monitor --user 別忘了帶 --user,不然會連到 system bus 看不到東西。

歡迎大家跟我分享你下的command和結果呦!

#!/usr/bin/env python3
import sys
import random
import dbus
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib

BUS_NAME = "org.citybonnie.Hello"
OBJ_PATH = "/org/citybonnie/Hello"
IFACE = "org.citybonnie.Hello"

CITIES = [
"Taipei", "Florence", "London", "Oxford", "Cambridge",
"Brisbane", "Sydney", "Tuscany", "Verona", "Milan"
]

class HelloService(dbus.service.Object):
def __init__(self, bus):
self._bus = bus
self._name = dbus.service.BusName(BUS_NAME, bus)
super().__init__(bus, OBJ_PATH)

# properties
self._mood = "curious"
self._counter = dbus.Int32(0)

# 每 5 秒自動送一張 Postcard(signal)
GLib.timeout_add_seconds(5, self._auto_postcard)

# -----------------------
# Methods
# -----------------------
@dbus.service.method(dbus_interface=IFACE,
in_signature="s", out_signature="s")
def SayHello(self, name):
"""印出 hello, 你的名字 並回傳同一句話"""
msg = f"hello, {name}"
print(msg, flush=True)

self._counter = dbus.Int32(int(self._counter) + 1)
return msg

@dbus.service.method(dbus_interface=IFACE,
in_signature="ss", out_signature="")
def SendPostcard(self, city, message):
"""立即送出一張明信片(Signal)"""
self.Postcard(city, message)

# -----------------------
# Signals
# -----------------------
@dbus.service.signal(dbus_interface=IFACE, signature="ss")
def Postcard(self, city, message):
"""廣播:城市 + 訊息"""
pass

def _auto_postcard(self):
"""每 5 秒自動送一張 Postcard,並遞增 Counter。"""
city = random.choice(CITIES)
self._counter = dbus.Int32(int(self._counter) + 1)
message = f"Counter={int(self._counter)} | Mood={self._mood}"
self.Postcard(city, message)
return True # True 表示持續排程

# -----------------------
# Properties(透過 org.freedesktop.DBus.Properties)
# -----------------------
@dbus.service.property(dbus_interface=IFACE, signature="s")
def Mood(self):
return self._mood

@Mood.setter
def Mood(self, value):
# 允許從 busctl set-property 寫入
self._mood = str(value)

@dbus.service.property(dbus_interface=IFACE, signature="i")
def Counter(self):
return self._counter

@Counter.setter
def Counter(self, value):
self._counter = dbus.Int32(int(value))

def main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
# 用 user/session bus,避免 root 權限
bus = dbus.SessionBus()
service = HelloService(bus)
print(f"{BUS_NAME} running on session bus. Object={OBJ_PATH}", flush=True)
GLib.MainLoop().run()

if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
sys.exit(0)


留言
avatar-img
L'Angolo di Embedded
22會員
26內容數
這裡會有一些我對於OpenBMC, Embedded Software的學習與經驗分享, 本來只在Line社群跟大家互動, 但是有夥伴提出想要看到歷史文章的需求, 於是我決定把它放到這裡, 努力磨練自己的技術和文筆。
L'Angolo di Embedded 的其他內容
2025/09/15
D-Bus是Linux系統中進程間通信的關鍵技術,它提供了一種標準化、高效的機制,讓不同的程序能夠方便地互相溝通協作。本文將用通俗易懂的語言解釋D-Bus的核心概念,包括Bus、Bus Name、Object Path和Interface等,並通過故事方式幫助你理解其工作原理。
2025/09/15
D-Bus是Linux系統中進程間通信的關鍵技術,它提供了一種標準化、高效的機制,讓不同的程序能夠方便地互相溝通協作。本文將用通俗易懂的語言解釋D-Bus的核心概念,包括Bus、Bus Name、Object Path和Interface等,並通過故事方式幫助你理解其工作原理。
2025/09/15
介紹了 IPC (Inter-Process Communication) 和 Sysfs 在 Linux 嵌入式系統中的應用,並以生活化的比喻說明程序間通訊的概念,以及 Sysfs 作為虛擬檔案系統介面,如何簡化硬體存取與系統狀態監控。
2025/09/15
介紹了 IPC (Inter-Process Communication) 和 Sysfs 在 Linux 嵌入式系統中的應用,並以生活化的比喻說明程序間通訊的概念,以及 Sysfs 作為虛擬檔案系統介面,如何簡化硬體存取與系統狀態監控。
2025/09/15
介紹OpenBMC中的電源控制機制,特別是phosphor-state-manager在其中的核心角色。透過比喻和實際程式碼範例,闡述電源狀態轉換流程、不同系統的實作差異以及錯誤處理的重要性,並提供小練習引導讀者更深入瞭解。
2025/09/15
介紹OpenBMC中的電源控制機制,特別是phosphor-state-manager在其中的核心角色。透過比喻和實際程式碼範例,闡述電源狀態轉換流程、不同系統的實作差異以及錯誤處理的重要性,並提供小練習引導讀者更深入瞭解。
看更多
你可能也想看
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
Function的使用方式
Thumbnail
Function的使用方式
Thumbnail
對於上班族來說,在處理文案、報告、新聞稿撰寫,或是資料彙整、簡報內容調整等,要是有一個好用小幫手可以支持,絕對能省不少時間與心力。特別在推出Chat GPT後,雖然有說對不少產品帶來衝擊,但也是工作上的好幫手,不過它的付費版卻不便宜....
Thumbnail
對於上班族來說,在處理文案、報告、新聞稿撰寫,或是資料彙整、簡報內容調整等,要是有一個好用小幫手可以支持,絕對能省不少時間與心力。特別在推出Chat GPT後,雖然有說對不少產品帶來衝擊,但也是工作上的好幫手,不過它的付費版卻不便宜....
Thumbnail
獲取Image docker pull 查看Image docker images 可以查看REPOSITORY、TAG、IMAGE ID、CREATED與SIZE。 創建Image docker build [OPTIONS] PATH | URL | - 上傳Imag
Thumbnail
獲取Image docker pull 查看Image docker images 可以查看REPOSITORY、TAG、IMAGE ID、CREATED與SIZE。 創建Image docker build [OPTIONS] PATH | URL | - 上傳Imag
Thumbnail
上回說明的手動下指令,傳出訊息。為了節省手動輸入之動作,將欲執行的curl指令內容,事先作成執行檔。當需要傳送訊息時,只要按兩下執行檔,便可立刻傳出訊息至LINE群組內之全員 2. 說明 2.1 因每次要傳送內容不同,將這些會變動的訊息資料,輸入後保存 於bat執行檔內
Thumbnail
上回說明的手動下指令,傳出訊息。為了節省手動輸入之動作,將欲執行的curl指令內容,事先作成執行檔。當需要傳送訊息時,只要按兩下執行檔,便可立刻傳出訊息至LINE群組內之全員 2. 說明 2.1 因每次要傳送內容不同,將這些會變動的訊息資料,輸入後保存 於bat執行檔內
Thumbnail
前言 大家好上次我們教了如何建立自己的 Docker Image,今天我們要來教怎麼把自己做好的 Docker Image 上傳到 Docker Hub,如果以後自己在公司有搭建 Docker Registry,也可以用同樣方式上傳到公司的 Docker Registry 私有倉庫 登入 Doc
Thumbnail
前言 大家好上次我們教了如何建立自己的 Docker Image,今天我們要來教怎麼把自己做好的 Docker Image 上傳到 Docker Hub,如果以後自己在公司有搭建 Docker Registry,也可以用同樣方式上傳到公司的 Docker Registry 私有倉庫 登入 Doc
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News