fix(cleaner): filename check
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
// src/cleaner.rs
|
// src/cleaner.rs
|
||||||
|
|
||||||
use chrono::{Duration as ChronoDuration, TimeZone, Utc};
|
use chrono::{Duration as ChronoDuration, NaiveDate, TimeZone, Utc};
|
||||||
use sqlx::{PgPool, Row};
|
use sqlx::{PgPool, Row};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -162,29 +162,66 @@ async fn cleanup_files(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let threshold_date = threshold.date_naive();
|
||||||
|
|
||||||
let mut entries = tokio::fs::read_dir(log_dir).await?;
|
let mut entries = tokio::fs::read_dir(log_dir).await?;
|
||||||
while let Some(entry) = entries.next_entry().await? {
|
while let Some(entry) = entries.next_entry().await? {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.is_file() {
|
if path.is_file()
|
||||||
if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) {
|
&& let Some(file_name) = path.file_name().and_then(|n| n.to_str())
|
||||||
// 【重要】增加了前缀匹配,更加安全
|
{
|
||||||
if !file_name.starts_with(prefix) || !file_name.ends_with(".log") {
|
// 【重要】增加了前缀匹配,更加安全
|
||||||
continue;
|
if !file_name.starts_with(prefix) || !file_name.ends_with(".log") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut should_delete = false;
|
||||||
|
|
||||||
|
let rest = &file_name[prefix.len()..];
|
||||||
|
// 处理可能存在的连接符,比如 prefix="order-service",文件名是 "order-service-2023..."
|
||||||
|
let date_part = if rest.starts_with('-') || rest.starts_with('_') {
|
||||||
|
&rest[1..]
|
||||||
|
} else {
|
||||||
|
rest
|
||||||
|
};
|
||||||
|
if date_part.len() >= 10 {
|
||||||
|
let date_str = &date_part[0..10];
|
||||||
|
if let Ok(file_date) = NaiveDate::parse_from_str(date_str, "%Y-%m-%d") {
|
||||||
|
// 成功从文件名解析出日期!
|
||||||
|
println!(
|
||||||
|
" -> Parsed date from filename: {} ({})",
|
||||||
|
file_name, file_date
|
||||||
|
);
|
||||||
|
|
||||||
|
if file_date < threshold_date {
|
||||||
|
should_delete = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 解析失败,说明文件名格式不对,回退到使用 Mtime
|
||||||
|
should_delete = check_by_mtime(&entry, threshold).await;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// 长度不够,回退到 Mtime
|
||||||
|
should_delete = check_by_mtime(&entry, threshold).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let metadata = entry.metadata().await?;
|
if should_delete {
|
||||||
if let Ok(modified_sys) = metadata.modified() {
|
if let Err(e) = tokio::fs::remove_file(&path).await {
|
||||||
let modified: chrono::DateTime<Utc> = modified_sys.into();
|
eprintln!("Failed cleanup file {:?}: {}", path, e);
|
||||||
if modified < threshold {
|
} else {
|
||||||
if let Err(e) = tokio::fs::remove_file(&path).await {
|
println!("Removed expired log file: {:?}", path);
|
||||||
eprintln!("Failed cleanup file {:?}: {}", path, e);
|
|
||||||
} else {
|
|
||||||
println!("Removed expired log file: {:?}", path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn check_by_mtime(entry: &tokio::fs::DirEntry, threshold: chrono::DateTime<Utc>) -> bool {
|
||||||
|
if let Ok(metadata) = entry.metadata().await
|
||||||
|
&& let Ok(modified_sys) = metadata.modified()
|
||||||
|
{
|
||||||
|
let modified: chrono::DateTime<Utc> = modified_sys.into();
|
||||||
|
return modified < threshold;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user