mod app;
mod daemon;
mod ui;
use anyhow::Result;
use app::{App, Cli, CliCommand};
use clap::Parser;
fn main() -> Result<()> {
let cli = Cli::parse();
if let Some(command) = cli.command.clone() {
run_cli_command(&cli, command)
} else {
App::new(cli).run()
}
}
fn run_cli_command(cli: &Cli, command: CliCommand) -> Result<()> {
match command {
CliCommand::List => print_daemon_list(cli),
CliCommand::Status { unit } => print_status(&unit),
CliCommand::Journal { unit } => print_journal(cli, &unit),
CliCommand::Events { unit } => print_events(cli, &unit),
CliCommand::Start { unit } => run_action(&unit, daemon::DaemonAction::Start),
CliCommand::Stop { unit } => run_action(&unit, daemon::DaemonAction::Stop),
CliCommand::Restart { unit } => run_action(&unit, daemon::DaemonAction::Restart),
CliCommand::Reload { unit } => run_action(&unit, daemon::DaemonAction::Reload),
CliCommand::Enable { unit } => run_action(&unit, daemon::DaemonAction::Enable),
CliCommand::Disable { unit } => run_action(&unit, daemon::DaemonAction::Disable),
CliCommand::Term { unit } => run_action(&unit, daemon::DaemonAction::KillTerm),
CliCommand::Kill { unit } => run_action(&unit, daemon::DaemonAction::KillKill),
}
}
fn print_daemon_list(cli: &Cli) -> Result<()> {
let mut app = App::new(cli.clone());
app.daemons = daemon::load_daemons()?;
let rows = app.visible_indices();
println!(
"{:<44} {:<18} {:>8} {:>10} SIGNAL",
"UNIT", "STATE", "PID", "MEM"
);
for idx in rows {
let daemon = &app.daemons[idx];
println!(
"{:<44} {:<18} {:>8} {:>10} {}",
daemon.unit,
daemon.state_label(),
daemon
.main_pid
.map(|pid| pid.to_string())
.unwrap_or_else(|| "-".to_string()),
daemon::format_bytes(daemon.memory_bytes),
daemon.anomaly_summary()
);
}
Ok(())
}
fn print_status(unit: &str) -> Result<()> {
let unit = daemon::service_unit(unit);
let report = daemon::status_report(&unit)?;
print_report(&report)
}
fn print_journal(cli: &Cli, unit: &str) -> Result<()> {
let unit = daemon::service_unit(unit);
for line in daemon::load_journal(&unit, cli.lookback_hours, cli.journal_lines)? {
println!("{line}");
}
Ok(())
}
fn print_events(cli: &Cli, unit: &str) -> Result<()> {
let unit = daemon::service_unit(unit);
let journal = daemon::load_journal(&unit, cli.lookback_hours, cli.journal_lines)?;
for line in daemon::notable_events(&journal) {
println!("{line}");
}
Ok(())
}
fn run_action(unit: &str, action: daemon::DaemonAction) -> Result<()> {
let unit = daemon::service_unit(unit);
let report = daemon::apply_action(&unit, action)?;
print_report(&report)
}
fn print_report(report: &daemon::CommandReport) -> Result<()> {
if !report.output.is_empty() {
println!("{}", report.output);
}
if report.ok {
Ok(())
} else {
anyhow::bail!("{} failed", report.command)
}
}