【问题标题】:C++ Linux Service - How to use init.d + auto restart?C++ Linux 服务 - 如何使用 init.d + 自动重启?
【发布时间】:2012-11-18 08:45:21
【问题描述】:

我创建了一个 linux c++ 服务(它基本上是一个应用程序,但它通过 TCP/IP 处理请求非常频繁)。

我想知道如果出现问题(如崩溃)或服务器重新启动,是否有任何简单的方法让它“自动重启”?

我不确定如何将其设置为服务或设置 rc.d 脚本,我不确定如何在 linux 上执行此操作(我的服务器正在运行 ubuntu)如果重要的话)。

任何建议将不胜感激!

~乔希

【问题讨论】:

    标签: c++ linux


    【解决方案1】:

    这里的很多答案都建议使用“父应用”来执行此操作,但您最终会遇到与父应用相同的问题 - 一直是海龟。

    在许多 unix 类型系统中(尤其是历史上),init 进程是第一个执行的进程,并将执行(并自动重新启动)/etc/inittab 中定义的进程。

    因此,与其编写自己的看门狗或进程来自动重启 - 您可以使用它自动为您完成这项工作,并且由于它是 init 进程,如果它死了,系统还有很多事情要担心比你的服务。

    @doron 建议另一种好方法,如果您的服务应该为每个传入连接生成一个新进程,并且只有在它有传入连接时才起作用。

    最后,这些天来,在 Ubuntu 类型系统上的 init 进程(和 /etc/inittab)已被替换为 upstart - http://upstart.ubuntu.com/ - 一个更灵活的系统用于同样的事情。

    【讨论】:

    • 我假设您对我的答案投了反对票并发布了自己的答案。简而言之:这不是海龟一路下降。父应用程序非常小,因此完全可靠,因此不会崩溃。父应用程序不需要控制应用程序。此外,很多事情都可能出错,崩溃只是其中之一,但您的解决方案只能处理崩溃。例如:如果您想检查服务器是否仍在处理请求或冻结怎么办?
    • 虽然我同意看门狗方法并不难(shell 脚本可以完成同样的工作),但我强烈认为编写自己的方法对于使用系统的 init 或服务进程来说是一个非常糟糕的选择管理系统。
    • 如果有额外检查的需求,那么我认为system init/service管理系统启动的进程可以做这些,或者监控同一个系统启动的第二个服务进程,或者它分叉的一个。
    • 最后,我承认在某些情况下,使用 init/service 系统进行看门狗活动不是最好的解决方案(甚至不是一种选择),对于这些情况,您的 cmets 和 Burgos' cmets 是完全有效和有用的。如果可以,我会删除我的反对票,因为它们不正确。
    【解决方案2】:

    在我的产品中,我创建了看门狗进程,该进程在单独的进程中分叉和执行服务进程,并等待其终止。如果由于某种原因进程终止,看门狗进程将创建另一个线程并重新启动进程。

    如 cmets 中所述,您应该检查它崩溃的原因。首先,您可以读取程序退出值。

    这里有一个简单的程序可以帮助您入门:

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.h>
    
    int main()
    {
        create_process();
        return 0;
    }
    
    void create_process()
    {
        int exit_code;
        if(fork() == 0)
        {
            exec("./your_service");
        }
        else
        {
            wait(&exit_code);
            if(WIFEXITED(exit_code))
            {
                /* Program terminated with exit */
                /* If you want, you could decode exit code here using
                   WEXITSTATUS and you can start program again.
                */
                return;
            }
            else
    `       {
                    /* Program didn't terminated with exit, restart */
                create_process();
            }
    
        }
    }
    

    为了在系统启动时启动服务,只需编辑/etc/rc.local 脚本并附加命令以运行您的看门狗进程。

    【讨论】:

    • a thread 听起来不正确..它可能会破坏看门狗线程的内存并阻止重新启动..
    • 是的,你是对的 - 我从来没有想到它(这是非常简单的服务)。那么它应该使用system() 吗?
    • 您还应该得到一些诊断为什么它崩溃了。并且在重新启动前离开(比如3)秒。您可能会遇到程序尝试重新启动、崩溃、重新启动的问题 - 作为开发人员,您无法重新控制,因为硬盘正在达到峰值,以及 cpu 等。
    • @Burgos,不,你也不想要system(),只需要forkexec。不需要线程或system()
    • @Nemanja Boric,我测试了你的答案,但它在执行后表现不正确。谢谢。
    【解决方案3】:
    • 创建一个控制应用程序,在必要时启动并重新启动它。
    • 在您的应用程序中执行此操作 - 派生一个孩子,在那里运行程序,捕获停止/崩溃并在必要时派生新的孩子。一些工作代码可以在这里找到:monitoring the main app in c

    【讨论】:

    【解决方案4】:

    您可能想看看使用Inet Daemon。每次有新请求进入时,inet 守护进程都会启动一个新进程。因此,如果您的服务器发生崩溃,它只会在下一个请求进入时重新启动。

    【讨论】:

    • 这假设请求可以独立处理,并且没有共享状态。它还将为每个请求创建一个新进程。
    【解决方案5】:

    在 *NIX 上编写自动重启子进程的父应用程序的最简单方法是使用 shell 脚本:

    #!/bin/sh
    while true;
    do
        run_my_program;
    done
    

    您可以选择有此重定向输出、在后台运行等。 这并没有首先解决启动进程,但与用 C++ 编写父进程相比,它的工作量更少(结果完全相同)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-07
      • 2021-01-27
      • 2019-08-23
      • 2013-09-11
      • 2019-06-03
      • 2017-12-29
      • 2014-04-13
      • 1970-01-01
      相关资源
      最近更新 更多