Fix service discovery to detect all services regardless of state
- Use systemctl list-unit-files and list-units --all to find inactive services - Parse both outputs to ensure all services are discovered - Remove special SSH detection logic since sshd is in service filters - Rename interesting_services to service_name_filters for clarity - Now detects services in any state: active, inactive, failed, dead, etc.
This commit is contained in:
parent
eb268922bd
commit
5886426dac
@ -111,19 +111,29 @@ impl SystemdCollector {
|
|||||||
|
|
||||||
/// Auto-discover interesting services to monitor
|
/// Auto-discover interesting services to monitor
|
||||||
fn discover_services(&self) -> Result<Vec<String>> {
|
fn discover_services(&self) -> Result<Vec<String>> {
|
||||||
let output = Command::new("systemctl")
|
// First get all unit files (includes inactive services)
|
||||||
.arg("list-units")
|
let unit_files_output = Command::new("systemctl")
|
||||||
|
.arg("list-unit-files")
|
||||||
.arg("--type=service")
|
.arg("--type=service")
|
||||||
.arg("--state=running,failed,inactive")
|
|
||||||
.arg("--no-pager")
|
.arg("--no-pager")
|
||||||
.arg("--plain")
|
.arg("--plain")
|
||||||
.output()?;
|
.output()?;
|
||||||
|
|
||||||
if !output.status.success() {
|
// Then get all loaded units (includes running/failed services)
|
||||||
|
let units_output = Command::new("systemctl")
|
||||||
|
.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 command failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let output_str = String::from_utf8(output.stdout)?;
|
let unit_files_str = String::from_utf8(unit_files_output.stdout)?;
|
||||||
|
let units_str = String::from_utf8(units_output.stdout)?;
|
||||||
let mut services = Vec::new();
|
let mut services = Vec::new();
|
||||||
|
|
||||||
// Skip setup/certificate services that don't need monitoring (from legacy)
|
// Skip setup/certificate services that don't need monitoring (from legacy)
|
||||||
@ -142,7 +152,7 @@ impl SystemdCollector {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Define patterns for services we want to monitor (from legacy)
|
// Define patterns for services we want to monitor (from legacy)
|
||||||
let interesting_services = [
|
let service_name_filters = [
|
||||||
// Web applications
|
// Web applications
|
||||||
"gitea",
|
"gitea",
|
||||||
"immich",
|
"immich",
|
||||||
@ -183,10 +193,29 @@ impl SystemdCollector {
|
|||||||
"ark",
|
"ark",
|
||||||
];
|
];
|
||||||
|
|
||||||
for line in output_str.lines() {
|
// Parse both unit files and loaded units
|
||||||
|
let mut all_service_names = std::collections::HashSet::new();
|
||||||
|
|
||||||
|
// Parse unit files (includes inactive services)
|
||||||
|
for line in 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 loaded units (includes running/failed services)
|
||||||
|
for line in units_str.lines() {
|
||||||
let fields: Vec<&str> = line.split_whitespace().collect();
|
let fields: Vec<&str> = line.split_whitespace().collect();
|
||||||
if fields.len() >= 4 && fields[0].ends_with(".service") {
|
if fields.len() >= 4 && fields[0].ends_with(".service") {
|
||||||
let service_name = fields[0].trim_end_matches(".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);
|
debug!("Processing service: '{}'", service_name);
|
||||||
|
|
||||||
// Skip excluded services first
|
// Skip excluded services first
|
||||||
@ -207,8 +236,8 @@ impl SystemdCollector {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this service matches our interesting patterns
|
// Check if this service matches our filter patterns
|
||||||
for pattern in &interesting_services {
|
for pattern in &service_name_filters {
|
||||||
if service_name.contains(pattern) || pattern.contains(service_name) {
|
if service_name.contains(pattern) || pattern.contains(service_name) {
|
||||||
debug!(
|
debug!(
|
||||||
"INCLUDING service '{}' because it matches pattern '{}'",
|
"INCLUDING service '{}' because it matches pattern '{}'",
|
||||||
@ -218,21 +247,8 @@ impl SystemdCollector {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always include ssh/sshd if present
|
|
||||||
if !services.iter().any(|s| s.contains("ssh")) {
|
|
||||||
for line in output_str.lines() {
|
|
||||||
let fields: Vec<&str> = line.split_whitespace().collect();
|
|
||||||
if fields.len() >= 4 && (fields[0] == "sshd.service" || fields[0] == "ssh.service")
|
|
||||||
{
|
|
||||||
let service_name = fields[0].trim_end_matches(".service");
|
|
||||||
services.push(service_name.to_string());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(services)
|
Ok(services)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user