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