用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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值