Rust 在 CentOS 上的日志管理实践
一 方案总览与选择
- 使用日志门面 log 统一接口,配合具体实现库输出日志。常见实现:
- env_logger:简单、基于环境变量 RUST_LOG 控制级别,适合开发/小型服务与容器化场景。
- log4rs:功能完备,支持 YAML 配置、多 Appender、滚动策略、按模块级别,适合生产长期运行。
- tracing / tracing-subscriber:面向异步与结构化日志,生态与 Tokio 配套,适合 Web/异步服务。
- 在 CentOS 上,应用常以 systemd 服务运行,日志可同时落入 journald(便于集中管理)与 文件(便于落盘与归档)。
二 快速上手 env_logger
- 添加依赖(Cargo.toml):
- [dependencies]
- log = “0.4”
- env_logger = “0.9”
- 初始化与输出示例(main.rs):
- use log::{info, error};
use env_logger::Env;
fn main() {
env_logger::Builder::from_env(Env::default().default_filter_or(“info”)).init();
info!(“应用启动”);
error!(“发生错误”);
}
- 运行时通过环境变量控制级别与模块:
- RUST_LOG=debug cargo run
- RUST_LOG=mycrate=debug,mycrate::db=info cargo run
- 自定义格式(含时间戳):
- 需添加依赖:chrono = “0.4”
- env_logger::Builder::from_env(Env::default().default_filter_or(“info”))
.format(|buf, record| {
writeln!(buf, “{} [{}] {}”, chrono::Local::now().format(“%Y-%m-%d %H:%M:%S”), record.level(), record.args())
})
.init();
- 适用:开发、调试、容器与简单服务;不建议复杂文件滚动与多目标路由。
三 生产级方案 log4rs
- 添加依赖(Cargo.toml):
- [dependencies]
- log = “0.4”
- log4rs = “0.10”
- 配置文件 log4rs.yaml(示例:控制台 + 滚动文件,支持热加载):
- refresh_rate: 30 seconds
appenders:
stdout:
kind: console
file:
kind: file
path: “/var/log/myapp/app.log”
encoder:
pattern: “{d(%Y-%m-%d %H:%M:%S)} [{l}] {m}{n}”
root:
level: info
appenders:
- stdout
- file
- 初始化(main.rs):
- use log::info;
use log4rs::init_file;
fn main() {
init_file(“log4rs.yaml”, Default::default()).unwrap();
info!(“log4rs 已初始化”);
}
- 要点:
- 通过 refresh_rate 实现配置热更新;使用 pattern 自定义格式;可按模块设置 loggers 与级别,实现差异化输出。
- 建议将日志目录(如 /var/log/myapp)预先创建并设定权限(如 myapp:myapp 755),便于 systemd 与文件写入。
四 与 systemd 和 journald 集成
- 部署为服务(/etc/systemd/system/myapp.service):
- [Unit]
- Description=My Rust App
- After=network.target
- [Service]
- User=myapp
- Group=myapp
- ExecStart=/opt/myapp/target/release/myapp
- Restart=always
- RestartSec=3
- StandardOutput=journal
- StandardError=journal
-
如需同时落盘,可在程序内用 log4rs 写文件
- [Install]
- WantedBy=multi-user.target
- 常用 journalctl 查询:
- 查看日志:sudo journalctl -u myapp
- 实时跟踪:sudo journalctl -u myapp -f
- 按时间/级别过滤:sudo journalctl -u myapp --since “2025-12-09 10:00:00” -p err
- 说明:
- 将 StandardOutput/StandardError 设为 journal 时,应用的标准输出会被 journald 捕获;若程序内已写入文件(如 log4rs),则形成“双写”(journald + 文件),便于集中与落盘各取所需。
五 实践建议
- 库 vs 应用:编写库时仅依赖 log 门面;应用选择 env_logger/log4rs/tracing 之一,避免混用导致配置分散。
- 日志级别:生产默认 info,问题排查临时提升到 debug/trace;通过 RUST_LOG 或配置文件按模块细粒度控制。
- 时间与格式:统一包含 时间、级别、模块(target)、消息;在 systemd 场景,journal 已带时间,文件日志建议保留时间以便离线分析。
- 文件与轮转:长期运行服务优先使用 log4rs 的文件与滚动策略,避免单文件过大;目录与权限提前规划(如 /var/log/myapp)。
- 异步与性能:高并发/异步场景优先考虑 tracing 生态(如非阻塞写入、与 Tokio 集成);写入文件时结合 tracing-appender 的非阻塞 writer 降低对业务线程影响。