创建一个侦听端口的简单Rust守护程序 [英] Creating a simple Rust daemon that listens to a port

查看:174
本文介绍了创建一个侦听端口的简单Rust守护程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图在Rust中创建一个简单的守护程序,该守护程序将使用tcp_stream侦听端口并输出消息。但是,我遇到两个问题:

I've been trying to make a simple daemon in Rust that will listen to a port using tcp_stream and print the message. However, I'm running into two problems:

1)如果我的守护进程使用println !,它将崩溃。如果删除所有提及的println !,则守护程序将运行。制作守护程序时stdout / stdin如何工作?

1) If my daemon uses println!, it crashes. If I remove all mentions of println!, the daemon works. How does stdout/stdin work when making a daemon?

我在Rust邮件列表中找到的一个消息来源说:对于现代的init系统,例如systemd或launchctl,这很好用,应用程序开发人员不必关心关于守护进程和日志记录的操作也只需通过stdout完成。他们的意思是什么?

One source I found on the Rust mailing list says "With modern init systems, such as systemd or launchctl, this works very nicely and application developer doesn't have to care about daemonisation and logging is also done simply via stdout." What do they mean by this?

2)当我在非守护程序模式下运行以下代码时,curl不会立即返回(运行诸如<$ c $之类的东西) c> $ curl -XPOST localhost:9337 -d'hi')。我必须杀死curl才能让服务器打印某些内容。卷曲不自动关闭连接吗?

2) When I run the code below in non-daemon mode, curls don't immediately return (running something like $ curl -XPOST localhost:9337 -d 'hi'). I have to kill curl for the server to print something. Doesn't curl close the connection automatically? Shouldn't the sent bytes be available to the server after they are sent, not after the connection is closed?

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?

它们的意思是您不应该做任何花哨的东西来创建分叉守护程序。您的程序应该可以正常工作,直接将其操作记录到stdout中,而像systemd或launchctl这样的初始化系统将自动处理其他所有事情,包括启动,关闭,日志记录重定向,生命周期管理等。请认真考虑这种方法,因为它会使您的程序更加简单

They mean that you shouldn't do anything fancy like forking to create a daemon program. Your program should just work, logging its operations directly into stdout, and init systems like systemd or launchctl will automatically handle everything else, including startup, shutdown, logging redirection, lifecycle management etc. Seriously consider this approach because it would make your program much simpler.

但是,正确创建守护进程并不容易。您必须派生该进程,关闭并设置新的文件描述符,调整进程组,添加信号处理程序等。搜寻类似 fork守护程序 之类的文章,其中有很多有关如何创建的文章一个守护程序,您可以 看到,这并非易事。当然,您可以在Rust中执行类似的操作,因为它通过 libc 板条箱。不过,可能会有一些警告:例如,我不确定Rust运行时对 fork()系统调用的反应如何。

Creating a daemon process properly, though, is not simple. You have to fork the process, close and set up new file descriptors, tweak process groups, add signals handlers and more. Googling for something like "fork daemon" gives a lot of articles on how to create a daemon, and you can see that this is not an easy task. Certainly, you can do something like this in Rust, because it exposes all of the necessary system calls through libc crate. There can be some caveats, though: for example, I'm not sure how Rust runtime would react on fork() system call.

至于为什么当您使用 println!()时,您的守护程序失败,我怀疑是因为您脱离了子进程及其stdio句柄会自动关闭,Rust I / O例程对此不满意并触发任务失败。

As for why your "daemon" fails when you use println!(), I suspect it happens because you detach from your child process and its stdio handles are automatically closed, and Rust I/O routines are not happy with that and trigger a task failure.

这篇关于创建一个侦听端口的简单Rust守护程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆