mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-10 22:54:21 +00:00
feature: Use ps
as fallback to query CPU usage under macOS (#390)
When running without elevated permissions under macOS, sysinfo cannot query states of processes by root user, which results in 0.0% CPU usage for all this kind of processes (and state = Unknown). Here we use `ps`, which has SUID, as a fallback to query CPU usages. This can be potentially applied to other properties if needed in the future (we'll need a proper struct and parser).
This commit is contained in:
parent
3dd748c2f4
commit
b8d3b68e75
1 changed files with 51 additions and 0 deletions
|
@ -229,6 +229,37 @@ fn get_linux_cpu_usage(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn get_macos_cpu_usage(pids: &[i32]) -> std::io::Result<std::collections::HashMap<i32, f64>> {
|
||||
use itertools::Itertools;
|
||||
let output = std::process::Command::new("ps")
|
||||
.args(&["-o", "pid=,pcpu=", "-p"])
|
||||
.arg(
|
||||
pids.iter()
|
||||
.map(i32::to_string)
|
||||
.intersperse(",".to_string())
|
||||
.collect::<String>(),
|
||||
)
|
||||
.output()?;
|
||||
let mut result = std::collections::HashMap::new();
|
||||
String::from_utf8_lossy(&output.stdout)
|
||||
.split_whitespace()
|
||||
.chunks(2)
|
||||
.into_iter()
|
||||
.for_each(|chunk| {
|
||||
let chunk: Vec<&str> = chunk.collect();
|
||||
if chunk.len() != 2 {
|
||||
panic!("Unexpected `ps` output");
|
||||
}
|
||||
let pid = chunk[0].parse();
|
||||
let usage = chunk[1].parse();
|
||||
if let (Ok(pid), Ok(usage)) = (pid, usage) {
|
||||
result.insert(pid, usage);
|
||||
}
|
||||
});
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_uid_and_gid(path: &PathBuf) -> (Option<u32>, Option<u32>) {
|
||||
// FIXME: [OPT] - can we merge our /stat and /status calls?
|
||||
|
@ -566,6 +597,26 @@ pub fn get_process_data(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let unknown_state = ProcessStatus::Unknown(0).to_string().to_string();
|
||||
let cpu_usage_unknown_pids: Vec<i32> = process_vector
|
||||
.iter()
|
||||
.filter(|process| process.process_state == unknown_state)
|
||||
.map(|process| process.pid)
|
||||
.collect();
|
||||
let cpu_usages = get_macos_cpu_usage(&cpu_usage_unknown_pids)?;
|
||||
for process in &mut process_vector {
|
||||
if cpu_usages.contains_key(&process.pid) {
|
||||
process.cpu_usage_percent = if num_cpus == 0.0 {
|
||||
*cpu_usages.get(&process.pid).unwrap()
|
||||
} else {
|
||||
*cpu_usages.get(&process.pid).unwrap() / num_cpus
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(process_vector)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue