tcp - 创建一个监听端口的简单 Rust 守护进程

标签 tcp process daemon rust

我一直在尝试用 Rust 制作一个简单的守护进程,它将使用 tcp_stream 监听端口并打印消息。但是,我遇到了两个问题:

1) 如果我的守护进程使用 println!,它就会崩溃。如果我删除所有对 println! 的提及,守护进程就会工作。制作守护进程时,stdout/stdin 是如何工作的?

One source I found on the Rust mailing list说“使用现代初始化系统,如 systemd 或 launchctl,这工作得非常好,应用程序开发人员不必关心守护进程,日志记录也可以通过 stdout 简单地完成。”这是什么意思?

2) 当我在非守护进程模式下运行下面的代码时,curls 不会立即返回(运行类似 $ curl -XPOST localhost:9337 -d 'hi' 的代码)。我必须杀死 curl 才能让服务器打印一些东西。 curl 不会自动关闭连接吗?发送的字节不应该在发送后对服务器可用,而不是在连接关闭后可用吗?

extern crate getopts;
use getopts::{optflag,getopts};
use std::io::Command;
use std::io::net::tcp::{TcpListener};
use std::io::{Acceptor,Listener};
use std::os;

fn main() {
    let args: Vec<String> = os::args();
    let opts = [
        optflag("d", "daemon", "conver this into a daemon"),
    ];
    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m },
        Err(f) => { fail!(f.to_string()) }
    };

    // Create a daemon? if necessary
    if matches.opt_present("d") {
        let child = Command::new(args[0].as_slice())
                            .detached().spawn().unwrap();
        println!("Created child: {}", child.id());

        // Do I wrap this in unsafe?
        child.forget();
        return;
    }

    let listener = TcpListener::bind("127.0.0.1", 9337u16).ok().expect("Failed to bind");
    let mut acceptor = listener.listen().ok().expect("Could not listen");

    loop {
        let mut tcp_stream = acceptor.accept().ok().expect("Could not accept connection");
        println!("Accepted new connection");

        let message = tcp_stream.read_to_string().unwrap();
        println!("Received message {}", message);
    }
}

最佳答案

What do they mean by this?

他们的意思是你不应该做任何花哨的事情,比如创建一个守护程序。您的程序应该可以正常工作,将其操作直接记录到标准输出中,而 systemd 或 launchctl 等初始化系统将自动处理其他一切,包括启动、关闭、日志重定向、生命周期管理等。认真考虑这种方法,因为它会使您的程序更简单.

但是,正确地创建守护进程并不简单。您必须 fork 进程、关闭并设置新的文件描述符、调整进程组、添加信号处理程序等等。谷歌搜索类似 "fork daemon" 的内容给出了很多关于如何创建守护进程的文章,你can see这不是一件容易的事。当然,你可以在 Rust 中做这样的事情,因为它通过 libc 公开了所有必要的系统调用。箱。不过,可能会有一些注意事项:例如,我不确定 Rust 运行时将如何对 fork() 系统调用使用react。

至于为什么当你使用 println!() 时你的“守护进程”失败了,我怀疑这是因为你从你的子进程分离并且它的 stdio 句柄自动关闭,并且 Rust I/O例程对此不满意并触发任务失败。

关于tcp - 创建一个监听端口的简单 Rust 守护进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26354465/

相关文章:

java - 在 Java (Windows) 中杀死目录中的所有进程

logging - Hadoop 守护进程日志

unix - .NET Core 中的跨平台后台服务(想想 windows 服务/unix 守护进程)?

networking - 通过网络检查 3D 打印机状态的守护程序(空闲/打印)

c++ - C 套接字文件传输损坏的数据

c - 平行管道没有在 C 中关闭?

ruby-on-rails - Net::HTTP 启动与新建

unix - 为什么使用 `clone` 创建进程会导致内存不足故障?

python - 以编程方式发现公共(public) IP

sockets - 发送消息后断开与 TCP 套接字的连接是否保证交付?