如何将Rocket框架日志转移至文件?解决多线程控制台干扰问题
将Rocket日志定向到文件,避免干扰用户输入
方法一:利用Rocket的tracing日志系统配置文件输出
这是跨平台的推荐方案,Rocket基于tracing生态,通过配置tracing-subscriber可直接将日志写入文件。
步骤1:添加依赖
在Cargo.toml中补充所需依赖:
[dependencies] rocket = { version = "0.5.0-rc.3", features = ["json"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "file"] } tracing-appender = "0.2"
步骤2:修改代码配置日志
在启动Rocket的线程中先配置日志输出目标,再启动服务:
use std::fs::OpenOptions; use std::thread; use tokio::runtime::Runtime; use tracing_subscriber::fmt::writer::MakeWriterExt; #[rocket::main] async fn main() { // 启动Rocket线程 thread::spawn(|| { let rt = Runtime::new().unwrap(); rt.block_on(async { // 打开日志文件(不存在则创建,存在则追加) let log_file = OpenOptions::new() .create(true) .append(true) .open("rocket.log") .expect("无法打开日志文件"); // 配置tracing订阅者,将日志写入文件 tracing_subscriber::fmt() .with_writer(log_file) .with_env_filter("rocket=info,_=warn") // 可按需调整日志级别,如rocket=debug .init(); // 启动Rocket应用 let _rocket = web_page::rocket().launch().await; }); }); // 用户输入逻辑线程 start(); } // 示例用户输入处理函数 fn start() { use std::io::{self, Write}; loop { print!("请输入内容:"); io::stdout().flush().unwrap(); // 确保提示符立即输出 let mut input = String::new(); io::stdin().read_line(&mut input).unwrap(); println!("你输入的是:{}", input.trim()); } }
方法二:重定向Rocket线程的标准输出/错误到文件
这种方式直接操作系统文件描述符,适合快速实现(仅支持Unix/Linux/macOS平台)。
修改代码实现重定向
use std::fs::OpenOptions; use std::io::{self, Write}; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::thread; use tokio::runtime::Runtime; #[rocket::main] async fn main() { thread::spawn(|| { let rt = Runtime::new().unwrap(); rt.block_on(async { // 打开日志文件 let log_file = OpenOptions::new() .create(true) .append(true) .open("rocket.log") .expect("无法打开日志文件"); // 保存原有的stdout和stderr文件描述符 let original_stdout_fd = io::stdout().as_raw_fd(); let original_stderr_fd = io::stderr().as_raw_fd(); let log_fd = log_file.as_raw_fd(); // 重定向stdout和stderr到日志文件 unsafe { libc::dup2(log_fd, libc::STDOUT_FILENO); libc::dup2(log_fd, libc::STDERR_FILENO); } // 启动Rocket let _rocket = web_page::rocket().launch().await; // 可选:恢复原stdout/stderr(线程结束后自动失效) unsafe { libc::dup2(original_stdout_fd, libc::STDOUT_FILENO); libc::dup2(original_stderr_fd, libc::STDERR_FILENO); } }); }); start(); } fn start() { use std::io::{self, Write}; loop { print!("请输入内容:"); io::stdout().flush().unwrap(); let mut input = String::new(); io::stdin().read_line(&mut input).unwrap(); println!("你输入的是:{}", input.trim()); } }
说明:Windows平台需使用winapi库调用SetStdHandle实现类似重定向逻辑。
内容的提问来源于stack exchange,提问作者Yuniversia
相关产品推荐
相关产品推荐

