如何编写一个每次被杀死后都会重新启动的进程

0 linux shell process background-process

我想要与这个问题完全相反的问题。我想知道如何创建一个在被终止后继续重新启动的进程。有人能给我一个实施示例吗?

例如,假设我有一个简单的过程,它将时间戳和递增计数器连续记录到日志文件中,如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#define FILE_PATH "/home/lincoln/date.log"

int main() {

    time_t current_time;
    struct tm *time_info;
    int counter = 0;

    while (1) {
        FILE *file = fopen(FILE_PATH, "a");
        if (file == NULL){
          perror("Failed to open the file");
          return 1;
        }
        // Get the current timestamp
        time(&current_time);
        time_info = localtime(&current_time);

        // Format the timestamp
        char timestamp[25];
        strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", time_info);

        // Write timestamp and counter to the file
        fprintf(file, "%s | Counter: %d\n", timestamp, counter++);
        fflush(file);

        fclose(file);
        sleep(5); // Sleep for 5 seconds
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为了生成二进制文件(ELF 文件),我使用了以下命令:

gcc logger_file.c -o date_test
Run Code Online (Sandbox Code Playgroud)

(请注意,这只是一个例子。它可能是一个不断打印的“hello world”程序。我选择日志记录是因为我想观察它连续运行的效果。)

引用的问题(如果我错了请纠正我)来看,它是通过监视子进程的父进程来实现的。如果子进程被终止,父进程会重新启动它。我理解这个概念,但不知道它在实践中是如何实现的。

有人可以演示如何使用提供的二进制示例来实现它吗?(也欢迎链接参考我的研究更多内容。)

如果需要更多信息,请告诉我。

编辑:在我的实现中,我计划在嵌入式设备上进行。基本上,在我的工作环境中,我将sysVinit作为启动系统,将BusyBox v1.23.2作为在 armv7 处理器上运行的 3.18.44 内核上的工具集(我正在使用gcc-12-arm-linux-gnueabi-base工具链)。

Mar*_*ler 7

进程一旦死亡就无法自行复活。它已经死了,它实际上不能再做任何事情了(这就是重点)。

\n

您可以让一个主管检查进程的状态,并在旧进程死亡时生成一个新进程。

\n

几乎所有(除了一些小众或面向小型容器的)Linux 发行版都使这一点变得微不足道:systemd 可以做到这一点,您所需要做的就是编写一个 systemd 服务单元文件并将属性设置Restart=alwayson-abnormal、 或on-abort。就是这样!

\n

然后,systemd 充当主管(无需编写自己的主管来摆弄 procfs 或类似的东西),并且一切开箱即用,并且您仍然可以通过显式停止服务重新启动systemctl

\n

现在,您问在实践中如何做到这一点。我提到过procfs;这是方法之一:您只需查看 /proc/{PID} 目录或例如其中的内存映射。

\n

然而,主管通常是这样的(systemd 的 service.c 也是这样做的),他们注册一个SIGCHLD处理程序:当进程的子进程退出时,父进程会收到一个信号。因为主管实际上是通过 启动受监督进程作为子进程fork,所以这是有效的。

\n

因此,您大致需要以下从古老的 Oracle 指南和 Linux 手册页中摘录的内容man waitpid

\n
#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\nvoid proc_exit() {\n  int wstat;\n  pid_t pid;\n\n  while (1) {\n    int retval = waitpid(pid, &wstat, WNOHANG);\n    if (retval == 0)\n      return;\n    else if (retval == -1)\n      return;\n    else\n      printf("Return code: %d\\n", WEXITSTATUS(wstat));\n  }\n}\nint main() {\n  signal(SIGCHLD, proc_exit);\n  switch (fork()) {\n  case -1:\n    perror("main: fork");\n    exit(0);\n  case 0:\n    printf("I\'m alive (temporarily)\\n");\n    exit(42);\n  default:\n    pause();\n  }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

子进程看到forkreturn 0,所以它是打印 的进程"I\'m alive\xe2\x80\xa6。在这里,如果您想生成一个不同的可执行文件(即您的受监督进程),请调用execve.

\n