我使用C语言开发了IP Messenger,并且希望分享其中的一些实现细节,以使您完全理解我的问题。
当我从终端启动此过程时,一切工作正常。但是随后,我通过在/etc/init.d/
目录中添加启动脚本,为此程序创建了一个启动项以将其作为服务运行。
然后我使用service命令启动了服务,
# service ipmsnger start
现在,我可以使用ps
命令来查看进程正在运行。但是如果有消息到达,它不会显示弹出窗口。消息发件人从信使获取成功交付报告。会是什么原因呢?由用户从终端启动一个恶魔进程与由系统启动它作为启动服务之间有什么区别?
答案 0 :(得分:0)
我对init.d不太熟悉,因为如今systemd更为常见。 我假设您正在运行X11,而不是Wayland。
使用CAP_NET_RAW 并以显示对话框的用户身份运行程序。
或以超级用户身份运行该程序,更改为要显示的用户的UID。
您还必须将DISPLAY
(主要是:0
和DBUS_SESSION_BUS_ADDRESS
设置为unix:path=/run/user/<UID of user to display to>/bus
#include <libnotify/notify.h>
#include <unistd.h>
#include <errno.h>
int main(void) {
if (getuid() != (uid_t)1000 && setuid(1000) == -1) {
perror("setuid");
return -1;
}
if (setenv("DISPLAY", ":0", 0) == -1) {
perror("setenv DISPLAY");
return-1;
} // guessing 1000 as UID
if (setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path=/run/user/1000/bus", 1) == -1) {
perror("setenv DBUS");
return-1;
}
notify_init ("Hello world!");
NotifyNotification * Hello = notify_notification_new("Hello world",
"This is an example notification.", "dialog-information");
notify_notification_show(Hello, NULL);
g_object_unref(G_OBJECT(Hello));
notify_uninit();
return 0;
}
答案 1 :(得分:0)
当您从终端窗口启动程序时,它与您当前的登录会话相关联。这为它提供了在您的 GUI中显示弹出窗口所需的上下文。
但是请记住,Linux是一个多用户系统,甚至支持多个并发GUI会话。每个GUI都属于一个会话。没有任何一种机器真正的GUI的感觉。如果您将程序作为系统服务启动,则该程序未与任何特定的登录会话连接,因此它不知道您的GUI是否在那里显示任何内容。
鉴于该服务以root特权运行,它可能有可能发现登录会话并在其中弹出消息,但是您不能免费获得它。
我推断将程序作为服务运行的目的是使无法声明root特权的人可以使用它。在这种情况下,我建议将其重构为两个程序:以root身份运行的服务和不具有特权的客户端。希望用户在要接收弹出窗口的会话中像运行客户端一样。客户端向服务器注册自己。服务器从网络接收消息,并将其分发给注册的客户端以供显示。