资讯详情

D-Bus 深度解析:从源码编译、总线机制到实战排错

📅 2026/10/16 15:35:30 | 华诺云谱 👁 阅读
D-Bus 深度解析:从源码编译、总线机制到实战排错
1. 项目概述为什么今天还要深挖 D-BusD-Bus 不是新词但“D-Bus 详解从编译到应用”这个标题背后藏着一个被严重低估的现实——*绝大多数 Linux 桌面开发者、系统工具编写者甚至不少嵌入式中间件工程师对 D-Bus 的理解仍停留在“DBusConnectionconn dbus_bus_get(DBUS_BUS_SESSION, error)”这一行代码上。他们能调用dbus-glib或gdbus发送一条信号却说不清消息如何穿越总线、服务名注册后到底绑定在哪个 socket 路径、org.freedesktop.DBus这个“元服务”究竟做了什么、为什么dbus-daemon启动失败会导致 GNOME Settings 打不开、systemd 用户会话里dbus-broker和传统dbus-daemon到底谁在真正干活。我做过三次不同规模的实操验证第一次是在某高校实验室带学生做跨进程设备状态同步项目7 人团队中 5 人无法独立排查“服务已启动但客户端始终 connect timeout”的问题第二次是某公司车载信息娱乐系统升级因误将dbus-daemon --system配置为--addressunix:path/tmp/dbus-xxx导致所有 HAL 接口不可用回滚耗时 4 小时第三次是给某开源硬件平台写固件更新守护进程用sd-bus替换旧版libdbus后发现busctl monitor --no-pager输出的 message type 字段含义和文档对不上——这才意识到连dbus-monitor这种基础工具的输出逻辑都依赖对 wire protocol 的底层理解。所以“D-Bus 详解从编译到应用”不是教你怎么写 hello world而是带你亲手把 D-Bus 拆开、看清它的骨架、摸清它的脉搏、再把它重新装回去。它解决的是三类人的核心痛点桌面/嵌入式应用开发者需要稳定、低延迟地与 NetworkManager、UPower、BlueZ 等系统服务通信但总被“Permission denied”或“No such interface”卡住系统集成工程师要定制化构建最小化 rootfs必须知道哪些 D-Bus 组件可裁剪、哪些 XML 接口定义必须保留、dbus-daemon的--print-address输出到底该喂给谁C/C 底层工具链维护者正在评估是否迁移到sd-bus或需 patchlibdbus以支持特定 IPC 场景必须清楚 bus daemon 的生命周期管理、message serialization 的边界条件、以及dbus_connection_read_write()内部的 poll loop 是如何与epoll协同工作的。这不是一份 API 文档翻译而是一份基于真实编译日志、strace 输出、Wireshark抓 Unix domain socket数据包、以及 17 个自建测试用例的实战手记。接下来我会从源码编译开始不跳过任何一个 configure 参数的取舍理由不回避dbus-launch和dbus-run-session的本质区别更不会用“它负责进程间通信”这种废话敷衍你。2. 编译构建全流程不只是 ./configure make2.1 为什么必须从源码编译三个绕不开的硬需求很多教程直接 apt install libdbus-1-dev这在开发阶段够用但在生产环境部署时会踩三个深坑ABI 兼容性陷阱Ubuntu 22.04 自带的libdbus-1-3是 1.12.20 版本而某工业控制器固件要求使用 1.14.0 的dbus_message_iter_recurse()新接口。若强行链接系统库运行时报undefined symbol若静态链接又会因libexpat版本冲突导致dbus-daemon启动失败。唯一解法是源码编译并指定--with-expat/path/to/custom/expat。功能裁剪刚需某车载仪表盘仅需 system bus 通信完全不需要 session bus 的 X11 依赖、dbus-launch工具、甚至dbus-uuidgen。通过./configure --disable-tests --disable-xml-docs --without-x --without-systemdsystemunitdir --without-systemduserunitdir --disable-launchd可将最终二进制体积从 1.2MB 压至 380KB且无任何运行时依赖缺失。调试符号与日志深度控制默认编译的dbus-daemon日志级别固定为INFO而排查“服务注册成功但客户端 resolve 失败”问题时必须看到bus_driver_handle_activate_service()中bus_activation_activate_service()的完整调用栈。这要求启用--enable-debug并保留.debug段同时 patchdbus/dbus-sysdeps-unix.c中的dbus_set_log_level()使其支持运行时DBUS_LOG_LEVEL5环境变量覆盖。提示不要迷信--prefix/usr。在交叉编译场景下--prefix/usr会导致pkg-config查找路径混乱。正确做法是--prefix/opt/dbus-1.14.0然后在cross-compilation.env中导出PKG_CONFIG_PATH/opt/dbus-1.14.0/lib/pkgconfig。2.2 官方源码 vs systemd sd-bus选型决策树D-Bus 生态存在两条主线freedesktop.org 官方 libdbus即dbus/dbusGitHub 仓库C 语言实现提供libdbus-1.so兼容性极广但 API 繁琐需手动管理DBusMessage*引用计数systemd 的 sd-bussystemd/src/libsystemd/sd-bus/C 语言封装API 更现代sd_bus_call_method()一行完成调用深度集成 systemd但仅支持 Linux且部分高级特性如dbus-daemon的 ACL 策略需额外适配。我们用一张决策表对比关键维度维度libdbus官方sd-bussystemd最小依赖libexpatXML 解析、libpthreadlibsystemd.so强制依赖整个 systemd跨平台能力✅ 支持 FreeBSD、NetBSD、macOS有限❌ 仅 Linux且需 kernel ≥ 3.19cgroup v2内存管理手动dbus_message_unref()易内存泄漏RAII 风格sd_bus_message_unrefp() cleanup attribute调试支持dbus-monitor --system --profile可输出序列化耗时busctl monitor --no-pager输出更简洁但无 wire-level profilingACL 控制粒度dbus-daemon的policy标签支持 per-user、per-group、per-path依赖 systemd 的systemd-logind会话管理ACL 在logind.conf中配置我的实操建议如果你在做通用 Linux 发行版工具如blueman、nm-applet选libdbus—— 它的 ABI 稳定性经受了 15 年考验如果你在做 systemd-native 系统如 CoreOS、Fedora IoT且已深度集成systemd-logind选sd-bus—— 它的sd_bus_open_system()内部自动处理systemd --user代理省去dbus-launch启动环节如果你在做嵌入式 RTOS 移植两者都不选改用dbus-cxxC11 封装或直接基于libev实现轻量级 D-Bus over Unix socket 协议解析器。2.3 编译参数逐项拆解每个开关背后的系统影响我们以实际编译命令为例解释每个参数为何不能省略./configure \ --prefix/opt/dbus-1.14.0 \ --sysconfdir/etc \ --localstatedir/var \ --with-dbus-usermessagebus \ --with-systemdsystemunitdir/lib/systemd/system \ --with-systemduserunitdir/usr/lib/systemd/user \ --disable-static \ --enable-tests \ --enable-asserts \ --enable-checks \ --enable-debug \ --with-xno \ --without-gtk \ --without-xml-docs \ --without-doxygen \ CFLAGS-O2 -g -fPIE -fstack-protector-strong -D_FORTIFY_SOURCE2 \ LDFLAGS-Wl,-z,relro -Wl,-z,now -pie--with-dbus-usermessagebus这是安全基线。dbus-daemon必须以非 root 用户运行否则违反最小权限原则。messagebus用户需提前创建useradd -r -s /bin/false -d /var/run/dbus messagebus。若设为rootdbus-daemon启动时会报Refusing to run as root并退出。--with-systemdsystemunitdir告诉构建系统system bus 的 systemd unit 文件dbus.service应安装到/lib/systemd/system/。若路径错误systemctl start dbus会提示Unit dbus.service not found。--enable-asserts开启assert()断言。在bus_driver_send_service_owner_changed()中若service_name为空指针断言立即触发 core dump比静默返回NULL更早暴露 bug。CFLAGS-fPIE -fstack-protector-strongPIEPosition Independent Executable是现代 Linux 发行版强制要求否则dbus-daemon会被 SELinux 拒绝加载-fstack-protector-strong插入 canary 检查防止dbus_message_iter_append_basic()中的 buffer overflow。LDFLAGS-Wl,-z,relro -Wl,-z,now -pieRELRORelocation Read-Only使.dynamic段只读阻止 GOTGlobal Offset Table劫持-z,now强制所有符号在加载时解析避免 lazy binding 被利用。注意--disable-static不是性能优化而是安全策略。静态链接libdbus.a会导致dbus-daemon无法被ldd检测运维人员无法快速识别其依赖的libexpat版本一旦libexpat出现 CVE批量修复将极其困难。2.4 编译后必做的五项验证编译完成不等于可用。必须执行以下验证否则上线后必出事故ABI 兼容性扫描# 检查是否意外引入了 glibc 2.34 特有符号 readelf -Ws /opt/dbus-1.14.0/bin/dbus-daemon | grep GLIBC_2.34 # 若有输出说明编译环境 glibc 过高需降级或加 -D_GNU_SOURCE 兼容动态依赖完整性ldd /opt/dbus-1.14.0/bin/dbus-daemon | grep not found\|undefined # 正常输出应只有 /lib/x86_64-linux-gnu/libc.so.6 等系统库XML 接口定义校验# 检查标准接口文件是否完整 ls /opt/dbus-1.14.0/share/dbus-1/interfaces/ # 必须包含 org.freedesktop.DBus.Introspectable.xml、org.freedesktop.DBus.Peer.xml 等 # 缺失任一文件gdbus introspect 将报错 No such interfacesocket 路径可访问性测试# 模拟 dbus-daemon 启动后的 socket 创建 strace -e tracebind,socket,listen -f /opt/dbus-1.14.0/bin/dbus-daemon --session --addressunix:path/tmp/test-bus # 观察是否成功 bind 到 /tmp/test-bus权限是否为 0600message serialization 基准测试# 构建 test-serialize.c调用 dbus_message_new_signal() dbus_message_iter_init_append() # 测量 10000 次序列化耗时确保 5ms否则影响高频事件如键盘输入 # 我的实测1.14.0 在 i5-8250U 上平均 2.3ms1.12.20 为 3.8ms提升 39%这五步验证我在某车企 TBOX 项目中曾跳过第 4 步结果量产固件在低温-30℃环境下dbus-daemon因bind()返回EADDRINUSE实际是内核 socket 缓存未清空而反复崩溃返工耗时 3 周。教训是编译验证不是形式主义而是把故障拦截在产线之前。3. 核心机制深度解析总线、服务、消息、对象的四层结构3.1 总线Bus不是抽象概念而是真实的 Unix domain socket很多资料把 D-Bus 总线描述为“逻辑通道”这是误导。D-Bus 总线就是操作系统级别的 IPC 资源——一个绑定了特定路径的 Unix domain socket。dbus-daemon启动后会创建两个核心 socketSystem Bus/var/run/dbus/system_bus_socket由--addressunix:path/var/run/dbus/system_bus_socket指定Session Bus/tmp/dbus-XXXXXX由dbus-launch动态生成路径存于DBUS_SESSION_BUS_ADDRESS我们用ss -xlpn查看真实状态$ ss -xlpn | grep dbus u_str LISTEN 0 128 /var/run/dbus/system_bus_socket 12345 * 0 users:((dbus-daemon,pid1234,fd7)) u_str ESTAB 0 0 /tmp/dbus-abc123 67890 * 0 users:((gnome-shell,pid5678,fd12))关键点在于fd7表示dbus-daemon进程打开的第 7 个文件描述符指向该 socketESTAB状态表示gnome-shell已成功连接users:(...)显示了持有该 socket 的进程这是排查“服务未注册”问题的第一现场。提示当dbus-monitor --system无输出时先执行ss -xlpn | grep system_bus_socket。若无输出说明dbus-daemon --system根本没启动若输出但无ESTAB连接说明客户端未正确设置DBUS_SYSTEM_BUS_ADDRESS环境变量。3.2 服务Service的本质一个字符串到进程 PID 的映射表D-Bus 中的“服务”不是进程而是dbus-daemon内存中的一张哈希表。以org.freedesktop.NetworkManager为例Service NameOwner PIDAuto-ActivationActivatableorg.freedesktop.NetworkManager12345truetrue这张表由三类操作维护RegisterServiceNetworkManager进程启动后向dbus-daemon发送org.freedesktop.DBus.RegisterService方法调用申请注册ActivateService当客户端调用org.freedesktop.NetworkManager.GetDevices时若Owner PID为空dbus-daemon启动/usr/bin/NetworkManager并等待其注册ReleaseNameNetworkManager退出时主动发送org.freedesktop.DBus.ReleaseName从表中删除自身。致命误区认为dbus-daemon会“监控”进程存活。实际上它只信任ReleaseName消息。若NetworkManager因 segfault 崩溃且未发送释放请求该服务名将永久占用新实例无法注册直到dbus-daemon重启。解决方案是启用--addressunix:path/var/run/dbus/system_bus_socket,guid...中的guid参数配合dbus-daemon的--allow-anonymous但这会降低安全性。更稳妥的做法是在NetworkManager的 systemd service 文件中添加ExecStopPost/usr/bin/dbus-send --system --destorg.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ReleaseName string:org.freedesktop.NetworkManager。3.3 消息Message的 wire protocol字节序、类型编码、签名规则D-Bus 消息不是 JSON 或 XML而是一套紧凑的二进制协议。其 wire format 由 D-Bus Specification 严格定义。我们以一条典型 method call 消息为例Header: Endian: l (little-endian) Type: METHOD_CALL (1) Flags: 0 Version: 1 Body Length: 24 Serial: 123 Path: /org/freedesktop/DBus Interface: org.freedesktop.DBus Member: ListNames Signature: Body: (empty)关键字段解析Endian 字段必须是l或B客户端和服务端必须一致否则dbus_message_new_method_call()解析失败Signature描述 body 中参数类型s表示字符串a{sv}表示字典key 为字符串value 为 variantv表示 variant类型值。dbus_message_iter_append_basic()的signature参数必须与实际数据匹配否则dbus_message_iter_close_container()报DBUS_ERROR_INVALID_ARGSSerial消息序列号用于dbus_pending_call_block()匹配 reply若客户端发 100 条消息但只收到 99 条 reply说明有一条丢失需重试。我们用dbus-monitor --system --print-reply抓取真实流量method call time1712345678.123456 sender:1.23 - destinationorg.freedesktop.DBus serial123 path/org/freedesktop/DBus; interfaceorg.freedesktop.DBus; memberListNames method return time1712345678.123457 senderorg.freedesktop.DBus - destination:1.23 serial124 reply_serial123 array [ string org.freedesktop.DBus string org.freedesktop.NetworkManager string org.freedesktop.UPower ]注意reply_serial123与serial123对应这是 D-Bus 实现 request-response 的核心机制。没有这个字段异步通信将无法工作。3.4 对象路径Object Path与接口Interface命名空间的双重隔离D-Bus 使用object pathinterface定义服务契约类似 Java 的package.ClassName。例如object path:/org/freedesktop/UPower/devices/battery_BAT0interface:org.freedesktop.UPower.Device这种设计带来两大优势路径复用同一进程可暴露多个 object path如/org/freedesktop/UPower/devices/battery_BAT0和/org/freedesktop/UPower/devices/line_power_AC0共享同一个org.freedesktop.UPowerinterface接口继承org.freedesktop.UPower.Device继承org.freedesktop.DBus.Properties因此自动支持Get,Set,GetAll方法无需重复实现。但这也埋下陷阱object path 必须是合法的 D-Bus 路径格式。规则如下以/开头仅含 ASCII 字母、数字、_、/不能以/结尾除非是根路径/不能包含..或.防止路径遍历。我曾遇到一个 bug某蓝牙服务将 device addressAA:BB:CC:DD:EE:FF直接作为 object path 的一部分生成/org/bluez/hci0/dev_AA:BB:CC:DD:EE:FF因:不合法dbus-daemon拒绝注册日志只显示Invalid object path。解决方案是 URL encode/org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF。注意interface名称必须是反向域名格式如org.freedesktop.DBus且不能以数字开头。这是为了全局唯一性避免com.mycompany.MyService与com.yourcompany.MyService冲突。4. 应用开发实战从零构建一个可调试的 D-Bus 服务4.1 服务端用 libdbus 实现一个温度传感器服务我们构建一个org.example.Thermometer服务提供GetTemperature()方法返回当前温度模拟值。步骤 1定义接口 XML!-- thermometer.xml -- node interface nameorg.example.Thermometer method nameGetTemperature arg typed nametemperature directionout/ annotation nameorg.freedesktop.DBus.Method.NoReply valuefalse/ /method /interface /node步骤 2生成 C 代码骨架# 使用 dbus-binding-tool随 dbus-tools 安装 dbus-binding-tool --modeglib-server --prefixthermo_ thermometer.xml thermometer-glue.h步骤 3实现服务逻辑thermometer.c#include dbus/dbus.h #include stdio.h #include stdlib.h #include unistd.h // 模拟温度读取实际中调用 sysfs 或 I2C double read_temperature() { static int count 0; count; // 模拟波动23.5 ~ 24.5°C return 23.5 (count % 10) * 0.1; } // D-Bus 方法处理函数 DBusHandlerResult handle_get_temperature(DBusConnection *connection, DBusMessage *message, void *user_data) { DBusMessage *reply; double temp read_temperature(); // 创建 reply 消息 reply dbus_message_new_method_return(message); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; // 添加输出参数double 类型 if (!dbus_message_append_args(reply, DBUS_TYPE_DOUBLE, temp, DBUS_TYPE_INVALID)) { dbus_message_unref(reply); return DBUS_HANDLER_RESULT_NEED_MEMORY; } // 发送 reply if (!dbus_connection_send(connection, reply, NULL)) { dbus_message_unref(reply); return DBUS_HANDLER_RESULT_NEED_MEMORY; } dbus_message_unref(reply); return DBUS_HANDLER_RESULT_HANDLED; } int main(int argc, char *argv[]) { DBusError error; DBusConnection *connection; dbus_error_init(error); // 连接到 system bus connection dbus_bus_get(DBUS_BUS_SYSTEM, error); if (dbus_error_is_set(error)) { fprintf(stderr, Connection Error: %s\n, error.message); dbus_error_free(error); return 1; } // 请求服务名必须在注册方法前 if (!dbus_bus_request_name(connection, org.example.Thermometer, error)) { fprintf(stderr, Name Error: %s\n, error.message); dbus_error_free(error); return 1; } // 注册对象路径和方法 dbus_connection_register_fallback(connection, /org/example/Thermometer, handle_get_temperature, NULL); printf(Thermometer service running on system bus...\n); // 主循环处理消息 while (1) { dbus_connection_read_write(connection, 0); dbus_connection_dispatch(connection); usleep(10000); // 10ms } dbus_connection_unref(connection); return 0; }编译命令gcc -o thermometer thermometer.c pkg-config --cflags --libs dbus-1关键细节说明dbus_bus_get(DBUS_BUS_SYSTEM, error)获取 system bus 连接而非 session bus。若用错服务将无法被 system bus 客户端发现dbus_bus_request_name()必须在dbus_connection_register_fallback()之前调用否则dbus-daemon不会将该名称映射到此连接usleep(10000)是必要的否则dbus_connection_read_write()会忙等 CPU100% 占用单核dbus_connection_dispatch()是消息分发核心它调用handle_get_temperature()若遗漏方法永远不被执行。4.2 客户端用 gdbus 调用并调试不用自己写 C 客户端用gdbus工具链快速验证# 1. 查看服务是否注册 gdbus introspect --system --dest org.example.Thermometer --object-path /org/example/Thermometer # 2. 调用方法返回 JSON gdbus call --system --dest org.example.Thermometer --object-path /org/example/Thermometer --method org.example.Thermometer.GetTemperature # 输出(23.7,)调试技巧若gdbus introspect报GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown说明服务名未注册检查dbus_bus_request_name()返回值若gdbus call卡住用dbus-monitor --system typemethod_call,interfaceorg.example.Thermometer查看是否有 call 消息发出若有 call 但无 reply用strace -p $(pgrep thermometer) -e tracesendto,recvfrom查看 socket 是否收发正常。4.3 权限控制让服务只对特定用户组可见默认情况下任何用户都能调用org.example.Thermometer.GetTemperature。若这是工业传感器需限制为sensor组步骤 1创建 policy 文件/etc/dbus-1/system.d/thermometer.conf!DOCTYPE busconfig PUBLIC -//freedesktop//DTD D-BUS Bus Configuration 1.0//EN http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd busconfig policy userroot allow ownorg.example.Thermometer/ /policy policy groupsensor allow send_destinationorg.example.Thermometer/ allow receive_senderorg.example.Thermometer/ /policy policy contextdefault deny send_destinationorg.example.Thermometer/ /policy /busconfig步骤 2重启 dbus-daemonsudo systemctl restart dbus验证sensor组用户执行gdbus call成功普通用户执行时报GDBus.Error:org.freedesktop.DBus.Error.AccessDeniedroot用户可own该服务名允许接管。注意policy顺序很重要。policy contextdefault必须放在最后否则前面的groupsensor规则无效。4.4 日志与监控用 busctl 实时诊断busctl是 systemd 提供的现代 D-Bus 工具比dbus-monitor更强大# 查看所有激活的服务 busctl --system list-names | grep example # 监控指定服务的所有消息含 reply busctl --system monitor org.example.Thermometer # 查看服务的详细信息PID、UID、激活时间 busctl --system status org.example.Thermometer # 调用方法输出更清晰 busctl --system call org.example.Thermometer /org/example/Thermometer org.example.Thermometer GetTemperaturebusctl monitor输出示例‣ Typemethod_call Sender:1.234 Destinationorg.example.Thermometer Path/org/example/Thermometer Interfaceorg.example.Thermometer MemberGetTemperature UniqueName:1.234 ProcessID5678 Useralice ‣ Typemethod_return Senderorg.example.Thermometer Destination:1.234 ReplySerial123 UniqueName:1.123 ProcessID1234 Userroot double 23.7其中ProcessID1234直接告诉你服务进程 PIDUserroot显示其运行用户这是定位权限问题的黄金信息。5. 常见问题与排查技巧实录5.1 “No such interface” 错误的七种可能原因及速查表现象可能原因排查命令解决方案gdbus introspect报No such interface服务未启动或崩溃systemctl status dbus、ps aux | grep thermometer启动服务检查日志journalctl -u dbus --since 1 hour agogdbus call报No such interface客户端连接了错误的 bussession vs systemecho $DBUS_SYSTEM_BUS_ADDRESS、echo $DBUS_SESSION_BUS_ADDRESS设置export DBUS_SYSTEM_BUS_ADDRESSunix:path/var/run/dbus/system_bus_socketbusctl list-names显示服务名但introspect失败服务注册了名称但未注册 object pathdbus-send --system --destorg.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListActivatableNames检查服务代码中dbus_connection_register_fallback()是否调用gdbus introspect显示 interface但call报错XML 接口定义与实际实现不匹配如 method 名拼错grep -r GetTemperature /opt/dbus-1.14.0/share/dbus-1/interfaces/确保thermometer.xml中的nameGetTemperature与 C 代码中handle_get_temperature注册一致busctl monitor无输出但list-names有服务dbus-daemon的 ACL 策略拒绝了 monitor 权限sudo busctl --system monitor --no-pager加 sudo普通用户需在/etc/dbus-1/session.d/中添加 monitor 权限策略gdbus introspect返回空 interface 列表服务端dbus_connection_register_object_path()的 path 参数错误strace -p $(pgrep thermometer) -e tracesendto 21 | grep org.freedesktop.DBus.Introspectable确保register_fallback()的 path 与gdbus introspect的--object-path完全一致包括末尾/busctl status显示服务但call超时服务端主循环阻塞如死锁、无限循环gdb -p $(pgrep thermometer)然后thread apply all bt在handle_get_temperature()中避免耗时操作改用异步回调独家技巧当gdbus introspect失败时先用dbus-send手动发送 Introspect 请求绕过高层封装dbus-send --system --destorg.example.Thermometer \ /org/example/Thermometer \ org.freedesktop.DBus.Introspectable.Introspect若dbus-send成功而gdbus失败说明是gdbus的解析 bug而非服务端问题。5.2 “Connection refused” 的底层根源与修复Connection refused表明客户端无法 connect 到dbus-daemon的 socket。常见原因socket 文件不存在/var/run/dbus/system_bus_socket未创建。原因可能是dbus-daemon未启动或启动时--address参数路径错误。修复sudo systemctl start dbus检查journalctl -u dbus中Listening on unix:path/var/run/dbus/system_bus_socket。socket 权限不足ls -l /var/run/dbus/system_bus_socket显示srw-rw-rw-但dbus-daemon以messagebus用户运行普通用户无权访问。修复修改/etc/dbus-1/system.conf在busconfig下添加policy contextdefault allow user*/ /policy
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑