diff --git a/agent/src/collectors/systemd.rs b/agent/src/collectors/systemd.rs index 44fa26d..73c9ef9 100644 --- a/agent/src/collectors/systemd.rs +++ b/agent/src/collectors/systemd.rs @@ -128,12 +128,45 @@ impl SystemdCollector { .arg("--plain") .output()?; + // Also get user unit files (user-level services) + let user_unit_files_output = Command::new("systemctl") + .arg("--user") + .arg("list-unit-files") + .arg("--type=service") + .arg("--no-pager") + .arg("--plain") + .output()?; + + // And user loaded units + let user_units_output = Command::new("systemctl") + .arg("--user") + .arg("list-units") + .arg("--type=service") + .arg("--all") + .arg("--no-pager") + .arg("--plain") + .output()?; + if !unit_files_output.status.success() || !units_output.status.success() { - return Err(anyhow::anyhow!("systemctl command failed")); + return Err(anyhow::anyhow!("systemctl system command failed")); } + // User commands might fail if no user session, so check individually + let user_unit_files_success = user_unit_files_output.status.success(); + let user_units_success = user_units_output.status.success(); + let unit_files_str = String::from_utf8(unit_files_output.stdout)?; let units_str = String::from_utf8(units_output.stdout)?; + let user_unit_files_str = if user_unit_files_success { + String::from_utf8(user_unit_files_output.stdout).ok() + } else { + None + }; + let user_units_str = if user_units_success { + String::from_utf8(user_units_output.stdout).ok() + } else { + None + }; let mut services = Vec::new(); // Skip setup/certificate services that don't need monitoring (from legacy) @@ -220,6 +253,28 @@ impl SystemdCollector { } } + // Parse user unit files if available + if let Some(user_unit_files_str) = &user_unit_files_str { + for line in user_unit_files_str.lines() { + let fields: Vec<&str> = line.split_whitespace().collect(); + if fields.len() >= 2 && fields[0].ends_with(".service") { + let service_name = fields[0].trim_end_matches(".service"); + all_service_names.insert(service_name.to_string()); + } + } + } + + // Parse user loaded units if available + if let Some(user_units_str) = &user_units_str { + for line in user_units_str.lines() { + let fields: Vec<&str> = line.split_whitespace().collect(); + if fields.len() >= 4 && fields[0].ends_with(".service") { + let service_name = fields[0].trim_end_matches(".service"); + all_service_names.insert(service_name.to_string()); + } + } + } + // Now process all discovered services for service_name in &all_service_names { debug!("Processing service: '{}'", service_name);