如何让RUST在后台优雅运行并守护进程?

Wor*_*ink 8 service daemon rust

这就是我想要实现的目标

\n\n
root> ./webserver start   // Does not block the terminal after startup, runs in the background and the process is guarded\nroot> \n
Run Code Online (Sandbox Code Playgroud)\n\n

我当前的实现逻辑\xef\xbc\x9a

\n\n逻辑在后台运行\n\n
root> ./webserver start   // Does not block the terminal after startup, runs in the background and the process is guarded\nroot> \n
Run Code Online (Sandbox Code Playgroud)\n\n

这样rust就会在后台运行,不会阻塞终端,但是rust在后台打印的信息仍然会显示在终端上,退出终端时当前的rust程序也会退出

\n\n进程守护程序逻辑\n\n

我的想法是监听系统的退出信号,不处理退出请求

\n\n
SIGHUP       1          /* Hangup (POSIX).  */                  \nSIGINT       2          /* Interrupt (ANSI).  */                       \nSIGQUIT      3          /* Quit (POSIX).  */                        \nSIGTERM      15         /* Termination (ANSI).  */               \n
Run Code Online (Sandbox Code Playgroud)\n\n

代码:

\n\n
 use std::process::Command;\nuse std::thread;\nuse std::env;\nuse std::time::Duration;\n\nfn main() {\n    let args: Vec<String> = env::args().collect();\n    if args.len() == 2 {\n        if &args[1] == "start" {\n            // Main process start child process\n            let child = Command::new(&args[0])\n                .spawn().expect("Child process failed to start.");\n            println!("child pid: {}", child.id());\n            // Main process exit\n        }\n    } else {Is there any more elegant approach? Looking forward to your reply\n        // Main business logic\n        run webserver\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

还有更优雅的方法吗?期待你的答复。

\n

chu*_*500 11

TLDR:如果您确实希望您的流程像服务一样运行(并且永不退出),那么可能需要设置一个服务管理器。否则,就让它成为一个正常的过程。

进程守护进程

立即需要注意的一件事是,关于守护进程的大多数考虑因素与 Rust 作为一种语言无关,更多的是:

  1. 您的流程所针对的底层系统
  2. 守护进程生成后的确切行为

看了你的问题,看来你已经意识到了大部分。不幸的是,为了正确回答您的问题,我们必须深入研究流程的复杂性及其管理方式。应该注意的是,如果您可以接受启动基础架构中的重大平台依赖性,则现有的“服务”管理器是一个很好的解决方案。

正如您所看到的,如果您想要一个可以正常工作的简单部署(前提是它是针对相关系统编译的),那么这并不是一件简单的事情。这些只是裸机服务管理器。如果你想支持虚拟环境,你必须考虑 Kubernetes 服务、docker 化等。

这些工具的存在是因为管理系统上长时间运行的进程需要考虑很多因素:

  • 我的守护进程是否应该像服务一样运行并在被杀死(或者系统重新启动)时重生?上面的工具可以实现这一点。
  • 如果是服务,我的守护进程是否应该具有与其关联的状态以帮助维护?这可以帮助管理中断和构建水平扩展的工具。
  • 如果守护进程不应该是一个服务(在你的情况下,鉴于你的二进制文件的名称,这不太可能),那么还有更多的问题:它应该附加到父进程吗?它应该附加到登录进程组吗?

鉴于这可能变得多么复杂,我对您的流程的猜测是,只需直接运行该流程即可。根本不要守护进程。

为了进行测试,(如果您处于类 UNIX 环境中)您可以在后台运行您的进程:

./webserver start &
Run Code Online (Sandbox Code Playgroud)

这将在后台生成新进程,但将其附加到 shell 的进程列表中。这对于测试来说非常有用,因为如果该 shell 消失,系统将随之清理这些附加进程。

上面的代码会将 stderr 和 stdout 文件描述符引导回您的终端并打印它们。如果您希望避免这种情况,您可以随时输出重定向到其他地方。

对我来说,禁用像这样的进程的信号似乎不是正确的方法。一旦您需要保存状态或向客户端发送终止消息,请保存这些信号以优雅地退出进程。如果您执行上述操作,您的守护进程将只能通过kill -9 <pid>或 重新启动,或找到一些您尚未覆盖的非标准信号(其默认行为是终止)来杀死。