使用 dbus 从 Linux 服务中分离分叉进程

问题描述 投票:0回答:1

我在 Linux 上有一个服务。该服务需要启动不同的进程。例如,在某些条件下,例如网络事件时,服务应启动具有 GUI 的进程。 为此,我使用了 fork() 和 execvp()。 此外,我还通过根据我想要运行该进程的用户设置 uid 和 gid 来删除 root 权限。 然后,我相应地设置了 DISPLAY 和 XAUTHORITY 环境变量。

这有点效果。我的进程确实正在运行并且 GUI 已显示。然而值得注意的是,该进程并没有真正与服务分离。 例如:pkexec 不起作用。它总是尝试启动终端版本并失败。 另外,我不希望服务停止后我的进程就被终止。

我读到为此我应该使用 dbus 并使用它与 systemd 进行通信,并且 1)通过 systemd 启动进程或 2)让 systemd 以某种方式从服务中分离我的进程。

现在我不知道这是如何运作的。我可以打开总线,我也应该能够调用方法,但是我不知道哪种方法以及我想要做什么。

有人可以指导我正确的方向,我应该在 systemd 上调用哪种方法来在用户会话中启动进程或从我的服务中分离进程。

免责声明:设置 KillMode=none 可以解决进程终止问题,但据我所知,不建议这样做,也不能解决 pkexec 问题。

c linux service dbus
1个回答
0
投票

以我的热门评论开头......

  1. fork
  2. 在孙子中
    setsid
  3. 在孙子中
    setpgrp
  4. 关闭孙子中的所有标准单元

我创建了一个似乎有效的诊断程序。我没有对其进行过广泛测试。它没有设置任何环境,所以我不知道这会如何影响事情。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

void
launch_top(int argc,char **argv)
{
    pid_t top = getpid();

    // parent launching child
    pid_t pcld = fork();
    if (pcld != 0) {
        waitpid(pcld,NULL,0);
        sleep(2);
        printf("launch_top: killing self %d\n",top);
        kill(top,SIGTERM);
        exit(0);
    }

    // child launching grandchild
    pid_t gcld = fork();
    if (gcld != 0)
        exit(0);

    // grandchild launching target
    setsid();
    setpgrp();

    fclose(stdin);
    fclose(stdout);
    fclose(stderr);

    char *av[3];

    av[0] = argv[0];
    av[1] = "forever";
    av[2] = NULL;

    execvp(av[0],av);
    perror("launch_top/execvp");
    exit(9);
}

void
stay_alive(int argc,char **argv)
{

    FILE *xflog = fopen("stay.log","w");
    setlinebuf(xflog);

    for (int loop = 0;  loop < 10;  ++loop) {
        fprintf(xflog,"stay_alive: %d\n",loop);
        sleep(1);
    }

    fprintf(xflog,"stay_alive: success\n");
    fclose(xflog);

    exit(0);
}

int
main(int argc,char **argv)
{

    setlinebuf(stdout);

    // ultimate program that should stay alive
    if (argc > 1)
        stay_alive(argc,argv);

    // launcher service
    else
        launch_top(argc,argv);

    return 0;
}

这是父级的

stdout
输出:

launch_top: killing self 2564383

这是目标程序的示例输出日志

stay.log
,该程序应该保持活动状态并在原始/父进程被杀死的情况下幸存下来:

stay_alive: 0
stay_alive: 1
stay_alive: 2
stay_alive: 3
stay_alive: 4
stay_alive: 5
stay_alive: 6
stay_alive: 7
stay_alive: 8
stay_alive: 9
stay_alive: success
© www.soinside.com 2019 - 2024. All rights reserved.