当前位置: 首页 > article >正文

用systemd 来控制 qt 程序的启动, 停止 . 解决 qt.qpa.xcb: could not connect to display 问题


author: hjjdebug
date: 2024年 09月 28日 星期六 15:49:51 CST
description: 用systemd 来控制 qt 程序的启动,停止
解决 qt.qpa.xcb: could not connect to display 问题

1. 先写一个QT 的测试程序 basic,

让他不断打印数字.

$ cat main.cpp 
#include <QApplication>
#include <QThread>
#include <QDebug>

class MyThread: public QThread
{
	void run()
	{
		int count=0;
		while(1)
		{
			qDebug()<<"running:"<<count++;
			sleep(1);
		}
	}
};
int main(int argc, char *argv[])
{
	QApplication app(argc,argv);
	MyThread thread;
	thread.start();
	return app.exec();
}
1.1: 运行,正常
$ ./basic
running: 0
running: 1
running: 2
running: 3

2. 再写这个程序的服务配置文件

$ cat basic.service 
[Unit]
Description=Basic Test

[Service]
Type=simple
ExecStart=/home/hjj/test/qt//basic/basic
Restart=on-failure

[Install]
WantedBy=multi-user.target

3. 测试: 启动服务失败:

$ sudo systemctl start basic.service

4. 状态查询

$ sudo systemctl status basic.service

● basic.service - Basic Test
     Loaded: loaded (/etc/systemd/system/basic.service; disabled; vendor preset: enabled)
     Active: failed (Result: core-dump) since Fri 2024-09-27 09:18:56 CST; 5s ago
    Process: 6062 ExecStart=/home/hjj/test/qt//basic/basic (code=dumped, signal=ABRT)
   Main PID: 6062 (code=dumped, signal=ABRT)

927 09:18:56 hjj-7090 systemd[1]: basic.service: Scheduled restart job, restart counter is at 5.
927 09:18:56 hjj-7090 systemd[1]: Stopped Basic Test.
927 09:18:56 hjj-7090 systemd[1]: basic.service: Start request repeated too quickly.
927 09:18:56 hjj-7090 systemd[1]: basic.service: Failed with result 'core-dump'.
927 09:18:56 hjj-7090 systemd[1]: Failed to start Basic Test.

5. 详细系统日志

$ journalctl -u basic.service

-- Logs begin at Thu 2024-07-25 08:51:30 CST, end at Fri 2024-09-27 09:26:52 CST. --
927 09:18:53 hjj-7090 systemd[1]: Started Basic Test.
927 09:18:53 hjj-7090 basic[6043]: qt.qpa.xcb: could not connect to display
927 09:18:53 hjj-7090 basic[6043]: qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
927 09:18:53 hjj-7090 basic[6043]: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
927 09:18:53 hjj-7090 basic[6043]: Available platform plugins are: linuxfb, minimal, offscreen, vnc, xcb.
927 09:18:53 hjj-7090 systemd[1]: basic.service: Main process exited, code=dumped, status=6/ABRT
927 09:18:53 hjj-7090 systemd[1]: basic.service: Failed with result 'core-dump'.
927 09:18:54 hjj-7090 systemd[1]: basic.service: Scheduled restart job, restart counter is at 1.
927 09:18:54 hjj-7090 systemd[1]: Stopped Basic Test.
927 09:18:54 hjj-7090 systemd[1]: Started Basic Test.
927 09:18:54 hjj-7090 basic[6054]: qt.qpa.xcb: could not connect to display
927 09:18:54 hjj-7090 basic[6054]: qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
927 09:18:54 hjj-7090 basic[6054]: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
927 09:18:54 hjj-7090 basic[6054]: Available platform plugins are: linuxfb, minimal, offscreen, vnc, xcb.
927 09:18:54 hjj-7090 systemd[1]: basic.service: Main process exited, code=dumped, status=6/ABRT
927 09:18:54 hjj-7090 systemd[1]: basic.service: Failed with result 'core-dump'.
927 09:18:54 hjj-7090 systemd[1]: basic.service: Scheduled restart job, restart counter is at 2.
927 09:18:54 hjj-7090 systemd[1]: Stopped Basic Test.
927 09:18:54 hjj-7090 systemd[1]: Started Basic Test.
927 09:18:54 hjj-7090 basic[6057]: qt.qpa.xcb: could not connect to display
927 09:18:54 hjj-7090 basic[6057]: qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
927 09:18:54 hjj-7090 basic[6057]: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
927 09:18:54 hjj-7090 basic[6057]: Available platform plugins are: linuxfb, minimal, offscreen, vnc, xcb.
927 09:18:54 hjj-7090 systemd[1]: basic.service: Main process exited, code=dumped, status=6/ABRT
927 09:18:54 hjj-7090 systemd[1]: basic.service: Failed with result 'core-dump'.
927 09:18:55 hjj-7090 systemd[1]: basic.service: Scheduled restart job, restart counter is at 3.
927 09:18:55 hjj-7090 systemd[1]: Stopped Basic Test.
927 09:18:55 hjj-7090 systemd[1]: Started Basic Test.
927 09:18:55 hjj-7090 basic[6059]: qt.qpa.xcb: could not connect to display
927 09:18:55 hjj-7090 basic[6059]: qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
927 09:18:55 hjj-7090 basic[6059]: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
927 09:18:55 hjj-7090 basic[6059]: Available platform plugins are: linuxfb, minimal, offscreen, vnc, xcb.
927 09:18:55 hjj-7090 systemd[1]: basic.service: Main process exited, code=dumped, status=6/ABRT
927 09:18:55 hjj-7090 systemd[1]: basic.service: Failed with result 'core-dump'.
927 09:18:55 hjj-7090 systemd[1]: basic.service: Scheduled restart job, restart counter is at 4.
927 09:18:55 hjj-7090 systemd[1]: Stopped Basic Test.
927 09:18:55 hjj-7090 systemd[1]: Started Basic Test.
927 09:18:55 hjj-7090 basic[6062]: qt.qpa.xcb: could not connect to display
927 09:18:55 hjj-7090 basic[6062]: qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
927 09:18:55 hjj-7090 basic[6062]: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
927 09:18:55 hjj-7090 basic[6062]: Available platform plugins are: linuxfb, minimal, offscreen, vnc, xcb.
927 09:18:55 hjj-7090 systemd[1]: basic.service: Main process exited, code=dumped, status=6/ABRT
927 09:18:55 hjj-7090 systemd[1]: basic.service: Failed with result 'core-dump'.
927 09:18:56 hjj-7090 systemd[1]: basic.service: Scheduled restart job, restart counter is at 5.
927 09:18:56 hjj-7090 systemd[1]: Stopped Basic Test.
927 09:18:56 hjj-7090 systemd[1]: basic.service: Start request repeated too quickly.
927 09:18:56 hjj-7090 systemd[1]: basic.service: Failed with result 'core-dump'.
927 09:18:56 hjj-7090 systemd[1]: Failed to start Basic Test.

6. 错误原因: 环境变量不同所致!

systemd 的环境变量,只有区区17行

$ cat env.log
LANGUAGE=zh_CN
LC_ADDRESS=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
PWD=/
LC_PAPER=en_US.UTF-8
LANG=zh_CN.UTF-8
INVOCATION_ID=049b2226a6d74f39a2fb88aa82227756
LC_IDENTIFICATION=en_US.UTF-8
SHLVL=1
LC_TELEPHONE=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_TIME=en_US.UTF-8
JOURNAL_STREAM=8:92364
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
LC_NUMERIC=en_US.UTF-8
_=/usr/bin/env

而我自己command 的环境变量有61行之多.
经过洗礼才有印象, 最后经过反复测试,比较得到2个关键环境变量.

DISPLAY:=0
XAUTHORITY=/run/user/1000/gdm/Xauthority

7. 命令行下复现问题.

你可以如下测试一下.
$ unset DISPLAY
hjj@hjj-7090:~/test/qt/basic$ ./basic
qt.qpa.xcb: could not connect to display
qt.qpa.plugin: Could not load the Qt platform plugin “xcb” in “” even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: linuxfb, minimal, offscreen, vnc, xcb.

已放弃 (核心已转储)

8. 错误到底是在什么地方出现的?

错误出处,原来在QApplication app(argc,argv)中有大量的函数调用,而且大量访问环境变量getenv(),
而其中DISPLAY,XAUTHORITY 环境变量是不可缺少的!!
否则就会在下面函数中打印出错信息!!

QApplicationPrivate::createEventDispatcher
"+>in init_platform of kernel/qguiapplication.cpp:1200                                               
21 in QGuiApplicationPrivate::createPlatformIntegration of ../../include/QtCore/../../src/corelib/te
32 in QGuiApplicationPrivate::createEventDispatcher of kernel/qguiapplication.cpp:1472              
43 in QApplicationPrivate::createEventDispatcher of kernel/qapplication.cpp:188                    
54 in QCoreApplicationPrivate::init of kernel/qcoreapplication.cpp:865                            
65 in QGuiApplicationPrivate::init of kernel/qguiapplication.cpp:1501                            
76 in QApplicationPrivate::init of kernel/qapplication.cpp:546                                  
87 in QApplication::QApplication of kernel/qapplication.cpp:534                                
98 in main of main.cpp:19                                                                     

调试挺不爽的,可能是有-O2 优化吧,算了,不调试了!

9. 解决办法: 补足其所需要的环境变量.

具体实现办法有两种,
一种是: 让服务程序去调用脚本. 脚本内容是先设置环境变量,再调用执行程序.
另一种: 让服务程序先设置环境变量,再调用程序.

我这里给出第一种吧,

$ cat basic.sh 
#!/bin/bash
export XAUTHORITY=/run/user/1000/gdm/Xauthority
export DISPLAY=:0
/home/hjj/test/qt/basic/basic &

$ cat basic.service 
[Unit]
Description=Basic Test

[Service]
Type=forking
#EnvironmentFile=/home/hjj/test/qt/basic/basic.env
ExecStart=/home/hjj/test/qt/basic/basic.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target


第二种就是把环境变量写到一个文件中例如 basic.env

$ cat basic.env
XAUTHORITY=/run/user/1000/gdm/Xauthority
DISPLAY=:0

并在上述服务配置中打开basic.env , 则basic.sh 中可不用导出环境变量
不管背着还是抱着,都是要把环境变量配上.

10. 最后的结果

$ sudo systemctl status basic.service

● basic.service - Basic Test
     Loaded: loaded (/etc/systemd/system/basic.service; disabled; vendor preset: enabled)
     Active: active (running) since Sat 2024-09-28 14:59:52 CST; 1h 1min ago
    Process: 109495 ExecStart=/home/hjj/test/qt/basic/basic.sh (code=exited, status=0/SUCCESS)
   Main PID: 109498 (basic)
      Tasks: 3 (limit: 9097)
     Memory: 2.1M
     CGroup: /system.slice/basic.service
             └─109498 /home/hjj/test/qt/basic/basic

928 16:01:31 hjj-7090 basic.sh[109498]: running: 3698
928 16:01:32 hjj-7090 basic.sh[109498]: running: 3699
928 16:01:33 hjj-7090 basic.sh[109498]: running: 3700
928 16:01:34 hjj-7090 basic.sh[109498]: running: 3701
928 16:01:35 hjj-7090 basic.sh[109498]: running: 3702

http://www.kler.cn/news/330864.html

相关文章:

  • 工程师 - 如何配置DNS服务器
  • 基于yolov8调用本地摄像头并将读取的信息传入jsonl中
  • SpringBoot框架下的社区医院信息系统开发
  • Stream流的终结方法(二)——collect
  • 2024大二上js高级+ES6学习9.29(深/浅拷贝,正则表达式,let/const,解构赋值,箭头函数,剩余参数)
  • 并集运算的线段树维护方式
  • c++就业磁盘链式b树与b+树
  • 3. 将GitHub上的开源项目导入(clone)到本地pycharm上——深度学习·科研实践·从0到1
  • 滚雪球学MySQL[7.1讲]:安全管理
  • 【笔记】数据结构12
  • Dubbo和Http的调用有什么区别
  • 【Docker】docker的存储
  • el-table动态表头
  • 828华为云征文|部署音乐流媒体服务器 mStream
  • React返回上一个页面,会重新挂载吗
  • 【AI知识点】非独立同分布(non-iid, non-independent and identically distributed)
  • AR技术在电商行业的应用及优势有哪些?
  • 解决银河麒麟V10系统bash执行提示:无法执行:权限不够的问题
  • 远程过程调用RPC知识科普
  • 【Linux】进程管理:状态与优先级调度的深度分析