use log::{debug, error, trace, warn}; use serde::{Deserialize, Serialize}; use std::fs; use std::io; use std::path::Path; #[derive(Deserialize, Serialize, Debug, Default)] pub(crate) struct Ptypes { pub(crate) running: u32, // R => Running pub(crate) sleeping: u32, // S => Sleeping in an interruptible wait pub(crate) waiting: u32, // D => Waiting in uninterruptible disk sleep pub(crate) zombie: u32, // Z => Zombie pub(crate) stopped: u32, // T => Stopped (on a signal) or (before Linux 2.6.33) trace stopped pub(crate) stop: u32, // t => tracing stop (Linux 2.6.33 onward) //pub(crate) paging: u64, // W => Paging (only before Linux 2.6.0) pub(crate) dead: u32, // X => Dead (from Linux 2.6.0 onward) or x => Dead (Linux 2.6.33 to 3.13 only) pub(crate) wakekill: u32, // K => Wakekill (Linux 2.6.33 to 3.13 only) pub(crate) waking: u32, // W => Waking (Linux 2.6.33 to 3.13 only) pub(crate) idle: u32, // I => Idle (Linux 4.14 onward) } pub(crate) fn count_processes(proc_path: &Path) -> io::Result { let mut counts = Ptypes::default(); debug!("Staring count_processes, iterating over {:?}", proc_path); for entry_result in fs::read_dir(proc_path)? { let entry = entry_result?; let path = entry.path(); // Check if the directory name is a number (a PID) if path.is_dir() && path .file_name() .and_then(|s| s.to_str()) .unwrap_or("") .parse::() .is_ok() { let stat_path = path.join("stat"); trace!("now reading contents of {:?}", stat_path); if let Ok(stat_contents) = fs::read_to_string(&stat_path) { // Read whole file, we read from memory, so we can search ")" from behind. if let Some(pos) = stat_contents.rfind(")") { match stat_contents.as_bytes().get(pos + 2) { Some(&byteval) => { match byteval { 82 => counts.running += 1, // R 83 => counts.sleeping += 1, // S 68 => counts.waiting += 1, // D 84 => counts.stopped += 1, // T 116 => counts.stop += 1, // t //87 => counts.paging += 1, // W --> only before 2.6 !! 88 => counts.dead += 1, // X 120 => counts.dead += 1, // x 75 => counts.wakekill += 1, // K 87 => counts.waking += 1, // W 73 => counts.idle += 1, // I _ => warn!("unknown proc status value {}", byteval), } } None => { error!("Problem parsing stat data {}", stat_contents); } } } } else { error!("read_to_string failed for {:?}", stat_path); } } } Ok(counts) }