Rust系统日志处理库utmp-classic-raw的使用:高效解析和处理Unix/Linux utmp日志文件
Rust系统日志处理库utmp-classic-raw的使用:高效解析和处理Unix/Linux utmp日志文件
utmp-classic-raw介绍
utmp-classic-raw是一个用于读取原始Unix utmp文件的Rust库。需要注意的是,所有类Unix系统(包括所有GNU/Linux发行版、MacOS和除OpenBSD外的所有BSD系统)都使用较新的utmpx
文件格式,尽管它们仍称之为utmp
。这个库仅适用于原始的Unix utmp
文件格式,据我所知只有OpenBSD还在使用这种格式。
如果你需要在除OpenBSD外的其他系统上使用,你可能需要寻找一个utmpx
库,尽管大多数库都自称是utmp
库。
示例运行
库的根目录中包含了一个示例utmp
文件,你可以通过以下命令运行示例:
cargo run --package utmp-classic --example dump-utmp tests/samples/basic.utmp
历史背景
这个库是对utmp-rs
(由upsuper开发)的修改版本。它被更新为适用于OpenBSD仍在使用的经典AT&T Unix v1风格的utmp
文件。
完整示例代码
以下是使用utmp-classic-raw库解析utmp文件的完整示例:
use std::fs::File;
use std::io::Read;
use utmp_classic_raw::UtmpEntry;
fn main() -> std::io::Result<()> {
// 打开utmp文件
let mut file = File::open("/var/run/utmp")?;
// 读取文件内容
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
// 解析utmp条目
let entries = UtmpEntry::from_bytes(&buffer)?;
// 打印每个条目信息
for entry in entries {
println!("User: {:?}", entry.user);
println!("Terminal: {:?}", entry.line);
println!("Host: {:?}", entry.host);
println!("Login Time: {:?}", entry.time);
println!("------------------------");
}
Ok(())
}
代码说明
- 首先打开并读取utmp文件内容到缓冲区
- 使用
UtmpEntry::from_bytes
方法解析二进制数据为UtmpEntry结构 - 遍历所有条目并打印相关信息,包括:
- 用户名
- 终端设备
- 主机信息
- 登录时间
安装方法
在你的项目中运行以下Cargo命令:
cargo add utmp-classic-raw
或者在Cargo.toml中添加:
utmp-classic-raw = "0.1.3"
注意事项
- 该库主要针对OpenBSD系统,其他系统可能需要使用utmpx格式的库
- 解析前需要确保有足够的权限读取utmp文件
- 时间字段可能需要额外处理转换为可读格式
1 回复
Rust系统日志处理库 utmp-classic-raw
使用指南
完整示例代码
下面是一个综合使用 utmp-classic-raw
库的完整示例,展示了如何读取系统登录信息并生成统计报告:
use utmp_classic_raw::{UtmpEntry, UtmpReader};
use std::error::Error;
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn Error>> {
// 1. 读取当前登录用户
let current_users = get_current_users()?;
println!("当前登录用户: {:?}", current_users);
// 2. 分析登录历史
analyze_login_history()?;
// 3. 生成登录统计
generate_login_stats()?;
Ok(())
}
/// 获取当前登录用户列表
fn get_current_users() -> std::io::Result<Vec<String>> {
let mut users = Vec::new();
let reader = UtmpReader::open("/var/run/utmp")?;
for entry in reader.entries() {
if let Ok(UtmpEntry::UserProcess(entry)) = entry {
if let Some(user) = entry.user() {
users.push(user.to_string());
}
}
}
Ok(users)
}
/// 分析登录历史记录
fn analyze_login_history() -> std::io::Result<()> {
let mut reader = UtmpReader::open("/var/log/wtmp")?;
let mut count = 0;
println!("\n最近5次登录记录:");
// 反向迭代获取最新记录
for entry in reader.entries().rev().take(5) {
match entry {
Ok(UtmpEntry::UserProcess(entry)) => {
println!(
"[{}] 用户: {:8} 终端: {:8} 来源: {:15} 时间: {}",
count + 1,
entry.user().unwrap_or("unknown"),
entry.line().unwrap_or("?"),
entry.host().unwrap_or("local"),
entry.time()
);
count += 1;
}
_ => {}
}
}
Ok(())
}
/// 生成登录统计信息
fn generate_login_stats() -> std::io::Result<()> {
let mut reader = UtmpReader::open("/var/log/wtmp")?;
let mut stats = HashMap::new();
let mut total_logins = 0;
// 统计每个用户的登录次数
for entry in reader.entries() {
if let Ok(UtmpEntry::UserProcess(entry)) = entry {
if let Some(user) = entry.user() {
*stats.entry(user.to_string()).or_insert(0) += 1;
total_logins += 1;
}
}
}
println!("\n登录统计:");
println!("总登录次数: {}", total_logins);
println!("各用户登录次数:");
// 按登录次数排序输出
let mut stats_vec: Vec<_> = stats.into_iter().collect();
stats_vec.sort_by(|a, b| b.1.cmp(&a.1));
for (user, count) in stats_vec {
println!("{:>15}: {}", user, count);
}
Ok(())
}
代码说明
-
get_current_users() 函数:
- 读取
/var/run/utmp
文件 - 返回当前登录系统的用户列表
- 读取
-
analyze_login_history() 函数:
- 读取
/var/log/wtmp
文件 - 显示最近5次登录记录
- 包含用户名、终端、来源IP和时间信息
- 读取
-
generate_login_stats() 函数:
- 统计所有历史登录记录
- 计算每个用户的登录次数
- 按登录次数排序输出统计结果
编译运行
- 在 Cargo.toml 中添加依赖:
[dependencies]
utmp-classic-raw = "0.1"
- 运行程序需要 root 权限:
sudo cargo run
输出示例
程序运行后可能的输出示例:
当前登录用户: ["alice", "bob"]
最近5次登录记录:
[1] 用户: alice 终端: pts/0 来源: 192.168.1.100 时间: 2023-01-01 10:30:00
[2] 用户: bob 终端: pts/1 来源: 192.168.1.101 时间: 2023-01-01 09:15:00
[3] 用户: alice 终端: pts/0 来源: 192.168.1.100 时间: 2023-01-01 08:45:00
[4] 用户: charlie 终端: tty2 来源: local 时间: 2023-01-01 08:30:00
[5] 用户: alice 终端: pts/0 来源: 192.168.1.100 时间: 2023-01-01 08:15:00
登录统计:
总登录次数: 42
各用户登录次数:
alice: 20
bob: 15
charlie: 5
dave: 2
这个示例展示了 utmp-classic-raw
库的综合应用,包括读取当前登录用户、分析登录历史和生成统计报告等功能。