D-Bus——system 调用session 报错

news2024/10/6 10:26:42

以下代码是一个 session 服务和 systemd 服务 demo :

systemd DBus
#include <QCoreApplication>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusError>
#include <QDebug>

class TestObject : public QObject
{
    Q_OBJECT
public:
    TestObject() {
        registerSystemDBus();
        callSession()
    }

    void registerSystemDBus() {
        QDBusConnection systemBus = QDBusConnection::systemBus();

        if (!systemBus.isConnected()) {
            qDebug() << "Failed to connect to system bus:" << systemBus.lastError().message();
            return;
        }

        if (!systemBus.registerService("com.example.TestSystemdService")) {
            qDebug() << "Failed to register service:" << systemBus.lastError().message();
            return;
        }

        if (!systemBus.registerObject("/com/example/TestObject",
                                      this,
                                      QDBusConnection::ExportAllSlots)) {
            qDebug() << "Failed to register object:" << systemBus.lastError().message();
            return;
        }
    }
    
    void callSession()
    {
        QDBusInterface interface("com.example.TestService",
                                 "/com/example/TestObject",
                                 "local.session.MainWindow",
                                 QDBusConnection::sessionBus());

        if (!interface.isValid()) {
            qDebug() << "Failed to create interface:" << interface.lastError().message();
            return;
        }

        QDBusMessage reply = interface.call("testMethod");
        if (reply.type() == QDBusMessage::ErrorMessage) {
            qDebug() << "Call failed:" << reply.errorMessage();
        } else {
            qDebug() << "Call succeeded.";
        }
    }

public slots:
    void testMethod() {
        qDebug() << "testMethod called";
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    TestObject testObject;
    QString path = QProcessEnvironment::systemEnvironment().value("DBUS_SESSION_BUS_ADDRESS");
    qDebug() << "path is " << path; // path is  ""
    return a.exec();
}

#include "main.moc"



cmakelist

cmake_minimum_required(VERSION 3.14)

project(systemd LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
find_package(Qt5DBus)

find_package(PkgConfig REQUIRED)
pkg_check_modules(QGSettings REQUIRED gsettings-qt)

add_executable(systemd
  main.cpp
)
target_link_libraries(systemd Qt${QT_VERSION_MAJOR}::Core
    Qt5::DBus
    ${QGSettings_LIBRARIES})

install(TARGETS systemd
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
session DBus

#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <QDebug>
#include <QDBusConnection>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QString path = QProcessEnvironment::systemEnvironment().value("DBUS_SESSION_BUS_ADDRESS");
    qDebug() << "path is " << path; // path is  "unix:path=/run/user/1000/bus"
    registerSessionDBus();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::registerSessionDBus()
{
    QDBusConnection::sessionBus().registerService("com.example.TestService");
    if (!QDBusConnection::sessionBus().registerObject("/com/example/TestObject",
            this, QDBusConnection::ExportAllSlots)) {
        qDebug() << "fail";
    }
}

void MainWindow::testMethod()
{
    qDebug() << "test";
}


cmakelist

cmake_minimum_required(VERSION 3.5)

project(session VERSION 0.1 LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
find_package(Qt5DBus)

find_package(PkgConfig REQUIRED)
pkg_check_modules(QGSettings REQUIRED gsettings-qt)

set(PROJECT_SOURCES
        main.cpp
        mainwindow.cpp
        mainwindow.h
        mainwindow.ui
)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(session
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
    )
# Define target properties for Android with Qt 6 as:
#    set_property(TARGET session APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
#                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
    if(ANDROID)
        add_library(session SHARED
            ${PROJECT_SOURCES}
        )
# Define properties for Android with Qt 5 after find_package() calls as:
#    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
    else()
        add_executable(session
            ${PROJECT_SOURCES}
        )
    endif()
endif()

target_link_libraries(session PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt5::DBus ${QGSettings_LIBRARIES})

set_target_properties(session PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

install(TARGETS session
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(session)
endif()

        当在 Systemed DBus 服务中,调用 session DBus 服务的接口,会发现即使 session 服务在运行,但依然会报如下错误:

Failed to create interface: "Not connected to D-Bus server"

        此时当我们在 demo 中增加以下日志输出,会发现在 root 下,DBUS_SESSION_BUS_ADDRESS 输出为空。

QString path = QProcessEnvironment::systemEnvironment().value("DBUS_SESSION_BUS_ADDRESS");

qDebug() << "session service print path is " << path; // "unix:path=/run/user/1000/bus"
qDebug() << "system service print path is " << path; // ""

        而 DBUS_SESSION_BUS_ADDRESS 为空,即为导致报错的原因,在解释 DBUS_SESSION_BUS_ADDRESS 为空会导致报错的原因之前,先了解几个概念:

dbus-daemon: 是 D-Bus 守护进程的实际实现,用于管理和协调消息传递,作为 D-Bus 的消息中转枢纽,可分成 system 和 session 两种。

System Bus:这个总线用于系统范围内的通信,通常涉及到系统服务和守护进程。

Session Bus:这个总线用于用户会话范围内的通信,通常涉及到用户应用程序。

DBUS_SESSION_BUS_ADDRESS:环境变量,用于存储会话总线的地址。

dbus-daemon官方文档参数介绍

        当用户登录时,会启动一个 dbus-daemon --session 进程,这个进程会创建一个会话总线并生成一个唯一的地址。这个地址会存储在 DBUS_SESSION_BUS_ADDRESS 环境变量中。当某个应用程序需要和其他应用程序通信时,它会读取 DBUS_SESSION_BUS_ADDRESS 环境变量来找到会话总线并进行通信。如果这个环境变量为空或者没有正确设置,服务将无法连接到会话总线,从而导致无法找到目标服务文件。

参考文献

D-Bus Specification

dbus-daemon

systemd/User - ArchWiki

解决方案供参考

        如果你给 root 用户导入了普通用户的 DBUS_SESSION_BUS_ADDRESS 环境变量,但仍然不能访问会话总线(session bus)服务,可能有以下几个原因:

1. 权限问题

        会话总线的 Unix 套接字通常设置为只有特定用户才能访问。即使你将 DBUS_SESSION_BUS_ADDRESS 设置为指向普通用户的会话总线地址,root 用户可能没有访问该套接字的权限。

2. 会话总线的安全策略

        D-Bus 有一套安全策略,用于限制哪些用户和进程可以访问哪些服务。即使 root 用户可以访问会话总线地址,也可能被会话总线的安全策略阻止访问特定服务。

3. 会话总线的用户隔离

        会话总线通常设计为与用户会话隔离。每个用户会话有自己的会话总线,且这些总线是相互隔离的,防止不同用户会话之间的干扰。

解决方案

方法一:修改会话总线套接字权限

        你可以尝试修改会话总线套接字的权限,以允许 root 用户访问。这种方法比较危险,需要谨慎操作:

查看套接字的权限:

ls -l /run/user/1000/bus

修改套接字的权限(不推荐):

chmod 777 /run/user/1000/bus

        这种方法会将套接字的权限设置为所有用户可读写,但可能会带来安全风险。

方法二:使用 dbus-launch

可以使用 dbus-launch 在 root 会话中启动一个新的会话总线:

启动一个新的会话总线:

sudo dbus-launch --sh-syntax

        这会输出一组新的环境变量,包括 DBUS_SESSION_BUS_ADDRESS。

导出这些环境变量:

export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

运行需要访问会话总线的命令:

your_command_here

方法三:通过代理或中继访问

        可以通过代理或中继的方式在 root 环境中访问用户会话总线服务。这种方法需要设置一些额外的工具和配置。

        假设你需要让 root 用户访问普通用户的 D-Bus 服务,可以尝试以下步骤:

启动新会话总线

        (如果需要 root 用户有自己的会话总线):sudo dbus-launch --sh-syntax

导出新的会话总线环境变量

        将命令输出的环境变量导出到当前环境。

确保会话总线地址正确设置

        确保 DBUS_SESSION_BUS_ADDRESS 环境变量正确指向普通用户的会话总线地址。

测试访问服务        

        尝试从 root 用户运行需要访问会话总线服务的命令,确认是否能够成功访问。

# 获取普通用户的 DBUS_SESSION_BUS_ADDRESS
USER_DBUS_SESSION_BUS_ADDRESS=$(sudo -u your_username echo $DBUS_SESSION_BUS_ADDRESS)

# 切换到 root 用户并导出会话总线地址
sudo -i <<EOF
export DBUS_SESSION_BUS_ADDRESS=$USER_DBUS_SESSION_BUS_ADDRESS
your_command_here
EOF

总结

        即使将 DBUS_SESSION_BUS_ADDRESS 环境变量正确设置为普通用户的会话总线地址,root 用户可能仍然无法访问会话总线服务,原因包括权限问题、安全策略和用户会话隔离等。可以尝试修改套接字权限、使用 dbus-launch 启动新的会话总线或通过代理访问来解决这个问题,但每种方法都有其限制和风险。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1816247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文搞懂flex布局

上学读书的时候&#xff0c;学习flex布局&#xff0c;更多停留在理论知识层面。近来&#xff0c;经过工作实践&#xff0c;发现自己对flex布局的理解更加深入&#xff0c;运用起来更加熟练&#xff0c;也越发能感受到flex布局的强大灵活性&#xff0c;特来总结一波。若有错误之…

Android Glide loading Bitmap from RESOURCE_DISK_CACHE slow,cost time≈2 seconds+

Android Glide loading Bitmap from RESOURCE_DISK_CACHE slow,cost time≈2 seconds 加载一张宽高约100px多些的小图&#xff0c;是一张相当小的正常图片&#xff0c;loading Bitmap from RESOURCE_DISK_CACHE竟然耗时达到惊人的3秒左右&#xff01;&#xff08;打开Glide调试…

元宇宙数字化3D虚拟展馆

随着科技的飞速发展&#xff0c;我们迎来了一个全新的时代——元宇宙时代。在这个充满无限可能的虚拟世界中&#xff0c;元宇宙数字展馆搭建编辑器应运而生&#xff0c;以其卓越的技术和创新的理念&#xff0c;为用户带来了前所未有的沉浸式展览体验。 元宇宙数字展馆搭建编辑器…

普涨和补涨—2024年上半年全球投资趋势

全球大宗商品价格处在上涨周期&#xff0c;东吴证券认为上游能源行业股价还有继续上涨的空间。随着6月全球股指进一步上涨&#xff0c;预计港股可能还会迎来补涨行情。 一、我们观察的全球投资趋势&#xff1a; 1、全球股指普涨&补涨。全球风险资产进入2024年后普遍上涨&am…

Spark安装、解压、配置环境变量、WordCount

Spark 小白的spark学习笔记 2024/5/30 10:14 文章目录 Spark安装解压改名配置spark-env.sh重命名&#xff0c;配置slaves启动查看配置环境变量 工作流程maven创建maven项目配置maven更改pom.xml WordCount按照用户求消费额上传到spark集群上运行 安装 上传&#xff0c;直接拖拽…

一文讲清:生产报工系统的功能、报价以及如何选择

最近这几年&#xff0c;企业越来越注重生产的速度和成本&#xff0c;尤其是“性价比”&#xff0c;生产报工系统已经变成了制造业里不可或缺的一部分。不过&#xff0c;市场上生产报工系统的选择太多&#xff0c;价格也都不一样&#xff0c;这就给很多企业出了个难题&#xff1…

【Python数据魔术】:揭秘类型奥秘,赋能代码创造

文章目录 &#x1f680;一.运算符&#x1f308;1. 算术运算符&#x1f308;2. 身份运算符&#x1f308;3. 成员运算符⭐4. 增量运算符⭐5. 比较运算符⭐6. 逻辑运算符 &#x1f680;二.可变与不可变&#x1f680;三.字符串转义&#x1f680;四.编码与解码&#x1f4a5;1. 基础使…

SpringBoot 异常配置

系统异常处理 创建异常处理器类&#xff0c;类上添加ControllerAdvice注解。 package com.soft.exception;import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframewor…

Java的集合框架总结

Map接口和Collection接口是所有集合框架的父接口&#xff1a; Collection接口的子接口包括&#xff1a;Set接口和List接口 Map接口的实现类主要有&#xff1a;HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等 Set接口的实现类主要有&#xff1a;HashSet、Tr…

【数据结构】二叉树:一场关于节点与遍历的艺术之旅

专栏引入 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我想让大家…

数据结构之链表的经典笔试题

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 203. 移除链表元素 206. 反转链表 876. 链表的中间节点 面试题 02.02. 返回倒数第k个节点 …

零基础非科班也能掌握的C语言知识22 预处理详解(完结)

预处理详解 1.预处理符号2.#define 定义常量3.#define 定义宏4.带有副作用的宏参数5.宏替换的规则6.宏函数的对比6.1 例子6.1 .16.1.26.1.3 7.命名约定8.undefin9.命令行定义(博主没办法演示)10.条件编译11.头文件的包含11.1本地文件11.2库文件的包含11.3 嵌套文件的包含 12.其…

软件安全测评有哪些测试流程?第三方检测机构进行安全测评的好处

在今天的高科技时代&#xff0c;软件产品已经成为人们生活和工作的重要组成部分。然而&#xff0c;与其普及和深入应用的&#xff0c;软件安全问题也日益凸显。 为了保障软件产品在使用过程中的安全性&#xff0c;进行安全测评是必不可少的。安全测评可以全面评估软件系统的安…

GPT-4o多模态大模型的架构设计

GPT-4o&#xff1a;大模型风向&#xff0c;OpenAI大更新 OpenAI震撼发布两大更新&#xff01;桌面版APP与全新UI的ChatGPT上线&#xff0c;简化用户操作&#xff0c;体验更自然。同时&#xff0c;全能模型GPT-4o惊艳亮相&#xff0c;跨模态即时响应&#xff0c;性能卓越且性价比…

Java集合自测题

文章目录 一、说说 List , Set , Map 三者的区别&#xff1f;二、List , Set , Map 在 Java 中分别由哪些对应的实现类&#xff1f;底层的数据结构&#xff1f;三、有哪些集合是线程不安全的&#xff1f;怎么解决呢&#xff1f;四、HashMap 查询&#xff0c;删除的时间复杂度五…

k8s中的pod域名解析失败定位案例

问题描述 我在k8s中启动了一个Host网络模式的pod&#xff0c;这个pod的域名解析失败了。 定位步骤 敲kubectl exec -it [pod_name] -- bash进入pod后台&#xff0c;查看/etc/resolv.conf&#xff0c;发现nameserver配的有问题。这里我预期的nameserver应该使用宿主机的&…

【Linux】线程(一)

谈论之前需要先谈论一些线程的背景知识 其中就有进程地址空间&#xff0c;又是这个让我们又爱又恨的东西 目录 背景知识&#xff1a;地址空间&#xff1a; 背景知识&#xff1a; 地址空间&#xff1a; 说在前边&#xff0c;OS通常分为4个核心模块&#xff1a;执行流管理&…

【qt】绘图

绘图 一.画家二.绘图事件三.坐标体系四.画笔1.setColor2.setWidth3.setStyle4.setCapStyle5.setJoinStyle6.给画家配置笔 五.画刷1.setColor2.setStyle3.给画家设置刷子 六.用到的类汇总1.QRect 矩形2.QPoint 点3.QImage 图片4.QPixmap 图片5.QLine 线6.QPainterPath 路径 七.开…

如何关闭端口被占用的进程

如何关闭端口被占用的进程 操作步骤一、打开命令提示符&#xff08;Command Prompt&#xff09;二、查看占用端口的进程三、kill杀死占用端口的进程 操作步骤 一、打开命令提示符&#xff08;Command Prompt&#xff09; 使用 win R 打开命令行模式 然后在命令行窗口输入下…

【LLM Agent 长文本】Chain-of-Agents与Qwen-Agent引领智能体长文本处理革命

前言 大模型在处理长文本上下文任务时主要存在以下两个问题&#xff1a; 输入长度减少&#xff1a;RAG的方法可以减少输入长度&#xff0c;但这可能导致所需信息的部分丢失&#xff0c;影响任务解决性能。扩展LLMs的上下文长度&#xff1a;通过微调的方式来扩展LLMs的上下文窗…