update list command
This commit is contained in:
parent
4a00d93759
commit
2182d78a63
@ -9,7 +9,7 @@ license = "MIT"
|
||||
[dependencies]
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
sysinfo = "0.33"
|
||||
tabled = "0.17"
|
||||
tabled = "0.18"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
dirs = "6.0.0"
|
||||
serde_json = "1.0"
|
||||
|
@ -1,7 +1,12 @@
|
||||
use crate::config::dump::DumpConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sysinfo::System;
|
||||
use tabled::{Table, Tabled};
|
||||
use sysinfo::{Pid, System};
|
||||
use tabled::{settings::Style, Table, Tabled};
|
||||
|
||||
const DEFAULT_ID: &str = "0";
|
||||
const DEFAULT_NAMESPACE: &str = "default";
|
||||
const DEFAULT_VERSION: &str = "N/A";
|
||||
const DEFAULT_USER: &str = "N/A";
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PmrProcess {
|
||||
@ -30,141 +35,158 @@ struct ProcessInfo {
|
||||
user: String,
|
||||
}
|
||||
|
||||
// 将秒数转换为可读的时间格式
|
||||
fn time_to_readable(seconds: u64) -> String {
|
||||
if seconds == 0 {
|
||||
return "0s".to_string();
|
||||
}
|
||||
|
||||
let days = seconds / (24 * 3600);
|
||||
let hours = (seconds % (24 * 3600)) / 3600;
|
||||
let minutes = (seconds % 3600) / 60;
|
||||
let secs = seconds % 60;
|
||||
let (days, hours, minutes, secs) = (
|
||||
seconds / 86400,
|
||||
(seconds % 86400) / 3600,
|
||||
(seconds % 3600) / 60,
|
||||
seconds % 60,
|
||||
);
|
||||
|
||||
let mut result = String::new();
|
||||
if days > 0 {
|
||||
result.push_str(&format!("{}d ", days));
|
||||
}
|
||||
if hours > 0 {
|
||||
result.push_str(&format!("{}h ", hours));
|
||||
}
|
||||
if minutes > 0 {
|
||||
result.push_str(&format!("{}m ", minutes));
|
||||
}
|
||||
if secs > 0 && days == 0 && hours == 0 {
|
||||
// 只在没有天和小时的时候显示秒
|
||||
result.push_str(&format!("{}s", secs));
|
||||
}
|
||||
let parts = vec![
|
||||
if days > 0 {
|
||||
format!("{}d", days)
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
if hours > 0 {
|
||||
format!("{}h", hours)
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
if minutes > 0 {
|
||||
format!("{}m", minutes)
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
if days == 0 && hours == 0 && secs > 0 {
|
||||
format!("{}s", secs)
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
];
|
||||
|
||||
result.trim().to_string()
|
||||
parts
|
||||
.into_iter()
|
||||
.filter(|s| !s.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
}
|
||||
|
||||
pub fn read_pmr_processes() -> Vec<PmrProcess> {
|
||||
let dump_config = DumpConfig::get_instance();
|
||||
match dump_config.list_processes() {
|
||||
Ok(processes) => processes
|
||||
.into_iter()
|
||||
.map(|p| PmrProcess {
|
||||
pmr_id: p.pmr_id,
|
||||
pid: p.pid,
|
||||
name: p.name,
|
||||
namespace: p.namespace,
|
||||
program: p.program,
|
||||
args: p.args,
|
||||
status: p.status,
|
||||
restarts: p.restarts,
|
||||
})
|
||||
.collect(),
|
||||
Err(e) => {
|
||||
dump_config
|
||||
.list_processes()
|
||||
.map(|v| {
|
||||
v.into_iter()
|
||||
.map(|p| PmrProcess {
|
||||
pmr_id: p.pmr_id,
|
||||
pid: p.pid,
|
||||
name: p.name,
|
||||
namespace: p.namespace,
|
||||
program: p.program,
|
||||
args: p.args,
|
||||
status: p.status,
|
||||
restarts: p.restarts,
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_else(|e| {
|
||||
eprintln!("Failed to read processes: {}", e);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn list_processes(system: bool) {
|
||||
let sys = System::new_all();
|
||||
|
||||
if system {
|
||||
let processes: Vec<ProcessInfo> = sys
|
||||
.processes()
|
||||
let processes: Vec<ProcessInfo> = if system {
|
||||
sys.processes()
|
||||
.iter()
|
||||
.map(|(&pid, process)| ProcessInfo {
|
||||
id: "0".to_string(),
|
||||
name: process.name().to_str().unwrap_or("unknown").to_string(),
|
||||
namespace: "default".to_string(),
|
||||
version: "N/A".to_string(),
|
||||
pid: pid.to_string(),
|
||||
uptime: time_to_readable(process.run_time()),
|
||||
restarts: "0".to_string(),
|
||||
status: process.status().to_string(),
|
||||
cpu: format!("{:.1}%", process.cpu_usage()),
|
||||
mem: format!("{:.1} MB", process.memory() as f64 / 1024.0 / 1024.0),
|
||||
user: "N/A".to_string(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let table = Table::new(processes).to_string();
|
||||
println!("{}", table);
|
||||
.map(|(pid, process)| create_process_info(*pid, process, &sys))
|
||||
.collect()
|
||||
} else {
|
||||
let pmr_processes = read_pmr_processes();
|
||||
let processes: Vec<ProcessInfo> = pmr_processes
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let status = if p.pid > 0 {
|
||||
// 检查进程是否真的在运行
|
||||
if let Some(sys_proc) = sys.process(sysinfo::Pid::from(p.pid as usize)) {
|
||||
let run_time = sys_proc.run_time();
|
||||
ProcessInfo {
|
||||
id: p.pmr_id.to_string(),
|
||||
name: p.name.clone(),
|
||||
namespace: p.namespace.clone(),
|
||||
version: "N/A".to_string(),
|
||||
pid: p.pid.to_string(),
|
||||
uptime: time_to_readable(run_time),
|
||||
restarts: p.restarts.to_string(),
|
||||
status: "running".to_string(),
|
||||
cpu: format!("{:.1}%", sys_proc.cpu_usage()),
|
||||
mem: format!("{:.1} MB", sys_proc.memory() as f64 / 1024.0 / 1024.0),
|
||||
user: "N/A".to_string(),
|
||||
}
|
||||
} else {
|
||||
// 进程不存在,但PID > 0,说明进程已经退出
|
||||
ProcessInfo {
|
||||
id: p.pmr_id.to_string(),
|
||||
name: p.name.clone(),
|
||||
namespace: p.namespace.clone(),
|
||||
version: "N/A".to_string(),
|
||||
pid: p.pid.to_string(),
|
||||
uptime: "0s".to_string(),
|
||||
restarts: p.restarts.to_string(),
|
||||
status: "stopped".to_string(),
|
||||
cpu: "0%".to_string(),
|
||||
mem: "0 MB".to_string(),
|
||||
user: "N/A".to_string(),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 原本就是停止状态
|
||||
ProcessInfo {
|
||||
id: p.pmr_id.to_string(),
|
||||
name: p.name.clone(),
|
||||
namespace: p.namespace.clone(),
|
||||
version: "N/A".to_string(),
|
||||
pid: "0".to_string(),
|
||||
uptime: "0s".to_string(),
|
||||
restarts: p.restarts.to_string(),
|
||||
status: "stopped".to_string(),
|
||||
cpu: "0%".to_string(),
|
||||
mem: "0 MB".to_string(),
|
||||
user: "N/A".to_string(),
|
||||
}
|
||||
};
|
||||
status
|
||||
})
|
||||
.collect();
|
||||
read_pmr_processes()
|
||||
.into_iter()
|
||||
.map(|p| create_pmr_process_info(&p, &sys))
|
||||
.collect()
|
||||
};
|
||||
|
||||
let table = Table::new(processes).to_string();
|
||||
println!("{}", table);
|
||||
let mut table = Table::new(processes);
|
||||
if system {
|
||||
table.with(Style::modern());
|
||||
} else {
|
||||
table.with(Style::rounded());
|
||||
}
|
||||
println!("{}", table);
|
||||
}
|
||||
|
||||
fn create_process_info(pid: Pid, process: &sysinfo::Process, sys: &System) -> ProcessInfo {
|
||||
let (status, sys_proc) = if process.name().to_str() == Some("system") {
|
||||
(process.status().to_string(), None)
|
||||
} else {
|
||||
(String::new(), sys.process(pid))
|
||||
};
|
||||
|
||||
let (cpu, mem) = if let Some(proc) = sys_proc.or(Some(process)) {
|
||||
(
|
||||
format!("{:.1}%", proc.cpu_usage()),
|
||||
format!("{:.1} MB", proc.memory() as f64 / 1024.0 / 1024.0),
|
||||
)
|
||||
} else {
|
||||
("0%".to_string(), "0 MB".to_string())
|
||||
};
|
||||
|
||||
ProcessInfo {
|
||||
id: DEFAULT_ID.to_string(),
|
||||
name: process.name().to_str().unwrap_or("unknown").to_string(),
|
||||
namespace: DEFAULT_NAMESPACE.to_string(),
|
||||
version: DEFAULT_VERSION.to_string(),
|
||||
pid: pid.as_u32().to_string(),
|
||||
uptime: time_to_readable(process.run_time()),
|
||||
restarts: "0".to_string(),
|
||||
status,
|
||||
cpu,
|
||||
mem,
|
||||
user: DEFAULT_USER.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_pmr_process_info(p: &PmrProcess, sys: &System) -> ProcessInfo {
|
||||
let (status, run_time, sys_proc) = if p.pid > 0 {
|
||||
let pid = Pid::from(p.pid as usize);
|
||||
match sys.process(pid) {
|
||||
Some(proc) => ("running".to_string(), proc.run_time(), Some(proc)),
|
||||
None => ("stopped".to_string(), 0, None),
|
||||
}
|
||||
} else {
|
||||
("stopped".to_string(), 0, None)
|
||||
};
|
||||
|
||||
let (cpu, mem) = sys_proc
|
||||
.map(|proc| {
|
||||
(
|
||||
format!("{:.1}%", proc.cpu_usage()),
|
||||
format!("{:.1} MB", proc.memory() as f64 / 1024.0 / 1024.0),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| ("0%".to_string(), "0 MB".to_string()));
|
||||
|
||||
ProcessInfo {
|
||||
id: p.pmr_id.to_string(),
|
||||
name: p.name.clone(),
|
||||
namespace: p.namespace.clone(),
|
||||
version: DEFAULT_VERSION.to_string(),
|
||||
pid: p.pid.to_string(),
|
||||
uptime: time_to_readable(run_time),
|
||||
restarts: p.restarts.to_string(),
|
||||
status,
|
||||
cpu,
|
||||
mem,
|
||||
user: DEFAULT_USER.to_string(),
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user