Fix logfiles growing indefinitely (fixes #750, #689, #1000)

This commit is contained in:
elkowar 2024-02-17 18:03:35 +01:00
parent 2656e238ca
commit 5b3dabf090
No known key found for this signature in database
GPG Key ID: 862BA3D7D7760F13
3 changed files with 64 additions and 9 deletions

View File

@ -33,7 +33,8 @@ All notable changes to eww will be listed here, starting at changes since versio
- Add `eww shell-completions` command, generating completion scripts for different shells - Add `eww shell-completions` command, generating completion scripts for different shells
### Fixes ### Fixes
- Fixed wrong values in `EWW_NET` - Fix wrong values in `EWW_NET`
- Fix logfiles growing indefinitely
## [0.4.0] (04.09.2022) ## [0.4.0] (04.09.2022)

View File

@ -10,6 +10,7 @@ use anyhow::{bail, Result};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EwwPaths { pub struct EwwPaths {
pub log_file: PathBuf, pub log_file: PathBuf,
pub log_dir: PathBuf,
pub ipc_socket_file: PathBuf, pub ipc_socket_file: PathBuf,
pub config_dir: PathBuf, pub config_dir: PathBuf,
} }
@ -43,14 +44,17 @@ impl EwwPaths {
log::warn!("The IPC socket file's absolute path exceeds 100 bytes, the socket may fail to create."); log::warn!("The IPC socket file's absolute path exceeds 100 bytes, the socket may fail to create.");
} }
Ok(EwwPaths { let log_dir = std::env::var("XDG_CACHE_HOME")
config_dir, .map(PathBuf::from)
log_file: std::env::var("XDG_CACHE_HOME") .unwrap_or_else(|_| PathBuf::from(std::env::var("HOME").unwrap()).join(".cache"))
.map(PathBuf::from) .join("eww");
.unwrap_or_else(|_| PathBuf::from(std::env::var("HOME").unwrap()).join(".cache"))
.join(format!("eww_{}.log", daemon_id)), if !log_dir.exists() {
ipc_socket_file, log::info!("Creating log dir");
}) std::fs::create_dir_all(&log_dir)?;
}
Ok(EwwPaths { config_dir, log_file: log_dir.join(format!("eww_{}.log", daemon_id)), log_dir, ipc_socket_file })
} }
pub fn default() -> Result<Self> { pub fn default() -> Result<Self> {
@ -66,6 +70,10 @@ impl EwwPaths {
self.log_file.as_path() self.log_file.as_path()
} }
pub fn get_log_dir(&self) -> &Path {
self.log_dir.as_path()
}
pub fn get_ipc_socket_file(&self) -> &Path { pub fn get_ipc_socket_file(&self) -> &Path {
self.ipc_socket_file.as_path() self.ipc_socket_file.as_path()
} }

View File

@ -11,6 +11,7 @@ use anyhow::{Context, Result};
use std::{ use std::{
cell::RefCell, cell::RefCell,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
io::Write,
os::unix::io::AsRawFd, os::unix::io::AsRawFd,
path::Path, path::Path,
rc::Rc, rc::Rc,
@ -41,6 +42,8 @@ pub fn initialize_server<B: DisplayBackend>(
} }
}; };
cleanup_log_dir(paths.get_log_dir())?;
if should_daemonize { if should_daemonize {
let fork_result = do_detach(paths.get_log_file())?; let fork_result = do_detach(paths.get_log_file())?;
@ -263,3 +266,46 @@ fn do_detach(log_file_path: impl AsRef<Path>) -> Result<ForkResult> {
Ok(ForkResult::Child) Ok(ForkResult::Child)
} }
/// Ensure the log directory never grows larger than 100MB by deleting files older than 7 days,
/// and truncating all other logfiles to 100MB.
fn cleanup_log_dir(log_dir: impl AsRef<Path>) -> Result<()> {
// Find all files named "eww_*.log" in the log directory
let log_files = std::fs::read_dir(&log_dir)?
.filter_map(|entry| {
let entry = entry.ok()?;
let path = entry.path();
if let Some(file_name) = path.file_name() {
if file_name.to_string_lossy().starts_with("eww_") && file_name.to_string_lossy().ends_with(".log") {
Some(path)
} else {
None
}
} else {
None
}
})
.collect::<Vec<_>>();
for log_file in log_files {
// if the file is older than a week, delete it
if let Ok(metadata) = log_file.metadata() {
if metadata.modified()?.elapsed()?.as_secs() > 60 * 60 * 24 * 7 {
log::info!("Deleting old log file: {}", log_file.display());
std::fs::remove_file(&log_file)?;
} else {
// If the file is larger than 200MB, delete the start of it until it's 100MB or less.
let mut file = std::fs::OpenOptions::new().append(true).open(&log_file)?;
let file_size = file.metadata()?.len();
if file_size > 200_000_000 {
let mut file_content = std::fs::read(&log_file)?;
let bytes_to_remove = file_content.len().saturating_sub(100_000_000);
file_content.drain(0..bytes_to_remove);
file.set_len(0)?;
file.write_all(&file_content)?;
}
}
}
}
Ok(())
}