Tem*_*muz 5 daemon tcp process rust
我一直在尝试在Rust中创建一个简单的守护进程,该守护进程将使用tcp_stream侦听端口并输出消息。但是,我遇到了两个问题:
1)如果我的守护进程使用println !,它将崩溃。如果删除所有对println!的提及,则守护程序将运行。创建守护程序时stdout / stdin如何工作?
我在Rust邮件列表中找到的一个消息来源说:“对于现代的init系统,例如systemd或launchctl,这非常有效,应用程序开发人员不必关心守护进程,并且记录也可以仅通过stdout完成。” 这是什么意思?
2)当我在非守护程序模式下运行以下代码时,curl不会立即返回(运行类似$ curl -XPOST localhost:9337 -d 'hi')。我必须杀死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);
}
}
Run Code Online (Sandbox Code Playgroud)
他们这是什么意思?
这意味着你不应该做任何花哨的事情,比如创建一个守护程序。您的程序应该可以正常工作,将其操作直接记录到标准输出中,而 systemd 或 launchctl 等初始化系统将自动处理其他一切,包括启动、关闭、日志重定向、生命周期管理等。请认真考虑这种方法,因为它会使您的程序更简单.
然而,正确创建守护进程并不简单。您必须分叉进程,关闭并设置新的文件描述符,调整进程组,添加信号处理程序等等。谷歌搜索诸如“fork daemon”之类的东西提供了很多关于如何创建守护程序的文章,您可以 看到这不是一件容易的事。当然,你可以在 Rust 中做这样的事情,因为它通过libccrate公开所有必要的系统调用。不过,可能有一些警告:例如,我不确定 Rust 运行时会如何对fork()系统调用做出反应。
至于为什么你的“守护进程”在你使用时失败println!(),我怀疑这是因为你从你的子进程中分离并且它的 stdio 句柄会自动关闭,并且 Rust I/O 例程对此不满意并触发任务失败。