mirror of
https://github.com/nushell/nushell.git
synced 2025-04-09 21:28:55 +02:00
Bumps [procfs](https://github.com/eminence/procfs) from 0.14.1 to 0.15.1. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/eminence/procfs/releases">procfs's releases</a>.</em></p> <blockquote> <h2>v0.15.1</h2> <h2>New features</h2> <ul> <li>Change Stat::comm documentation by <a href="https://github.com/rust1248"><code>@rust1248</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/251">eminence/procfs#251</a></li> <li>Add docs and a as_str method to MMPermission by <a href="https://github.com/eminence"><code>@eminence</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/252">eminence/procfs#252</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/rust1248"><code>@rust1248</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/251">eminence/procfs#251</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/eminence/procfs/compare/v0.15.0...v0.15.1">https://github.com/eminence/procfs/compare/v0.15.0...v0.15.1</a></p> <h2>v0.15.0</h2> <h2>New Features</h2> <ul> <li>Add /proc/iomem by <a href="https://github.com/tatref"><code>@tatref</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/216">eminence/procfs#216</a></li> <li>Add new functions to read various net files for a specific process by <a href="https://github.com/eminence"><code>@eminence</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/226">eminence/procfs#226</a></li> <li>add /proc/kpageflags by <a href="https://github.com/tatref"><code>@tatref</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/233">eminence/procfs#233</a></li> <li>Enable oppportunistic fd counting fast path by <a href="https://github.com/bobrik"><code>@bobrik</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/234">eminence/procfs#234</a></li> <li>add /proc/kpagecount by <a href="https://github.com/tatref"><code>@tatref</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/232">eminence/procfs#232</a></li> <li>Add new <code>/proc/meminfo</code> fields. by <a href="https://github.com/afranchuk"><code>@afranchuk</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/238">eminence/procfs#238</a></li> <li>impl Hash for kernel version by <a href="https://github.com/tatref"><code>@tatref</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/240">eminence/procfs#240</a></li> </ul> <h2>Bug fixes</h2> <ul> <li>fix chrono::Local::timestamp deprecated in chrono 0.4.23 by <a href="https://github.com/tatref"><code>@tatref</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/220">eminence/procfs#220</a></li> <li>Fix some minor documentation issues by <a href="https://github.com/eminence"><code>@eminence</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/225">eminence/procfs#225</a></li> <li>Fixes the reported path when a task's function returns an error by <a href="https://github.com/eminence"><code>@eminence</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/230">eminence/procfs#230</a></li> <li>fix shm size type by <a href="https://github.com/tatref"><code>@tatref</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/243">eminence/procfs#243</a></li> </ul> <h2>Breaking changes</h2> <ul> <li>ticks_per_second and page_size are infallible by <a href="https://github.com/eminence"><code>@eminence</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/235">eminence/procfs#235</a></li> <li>parse uid for /proc/net/{tcp,udp} by <a href="https://github.com/trinity-1686a"><code>@trinity-1686a</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/231">eminence/procfs#231</a></li> <li>Refactor and expose memory map processing. by <a href="https://github.com/afranchuk"><code>@afranchuk</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/237">eminence/procfs#237</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/trinity-1686a"><code>@trinity-1686a</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/231">eminence/procfs#231</a></li> <li><a href="https://github.com/afranchuk"><code>@afranchuk</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/238">eminence/procfs#238</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/eminence/procfs/compare/v0.14.2...v0.15.0">https://github.com/eminence/procfs/compare/v0.14.2...v0.15.0</a></p> <h2>MSRV Note</h2> <p>This <code>v0.15</code> release is only tested against the latest stable rust compiler, but is known to work with older versions (down to rust 1.48). Support for these older compilers may break in <code>procfs</code> patch releases. See also <a href="https://github-redirect.dependabot.com/eminence/procfs/issues/223">#223</a></p> <h2>v0.14.2</h2> <h2>New Features</h2> <ul> <li>Process: Namespace: Use openat instead of building a path by <a href="https://github.com/arilou"><code>@arilou</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/192">eminence/procfs#192</a></li> <li>add serde serialize/deserialize derives for public types by <a href="https://github.com/eliad-wiz"><code>@eliad-wiz</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/193">eminence/procfs#193</a></li> <li>Disabling default features on the <code>chrono</code> crate by <a href="https://github.com/Will-Low"><code>@Will-Low</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/210">eminence/procfs#210</a></li> <li>Implement smaps_rollup by <a href="https://github.com/TaborKelly"><code>@TaborKelly</code></a> in <a href="https://github-redirect.dependabot.com/eminence/procfs/pull/214">eminence/procfs#214</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="16ccc15aa1
"><code>16ccc15</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/eminence/procfs/issues/253">#253</a> from eminence/v0_15_1</li> <li><a href="4b5b61a89d
"><code>4b5b61a</code></a> Version 0.15.1</li> <li><a href="b7f66d5a8c
"><code>b7f66d5</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/eminence/procfs/issues/252">#252</a> from eminence/mmperms</li> <li><a href="af961235ff
"><code>af96123</code></a> Add docs and a as_str method to MMPermission</li> <li><a href="6c6ddbd42e
"><code>6c6ddbd</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/eminence/procfs/issues/251">#251</a> from rust1248/task/fix-comm-docs</li> <li><a href="7e7afab4f8
"><code>7e7afab</code></a> Change Stat::comm documentation</li> <li><a href="391bd13a0a
"><code>391bd13</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/eminence/procfs/issues/247">#247</a> from eminence/statat_nofollow</li> <li><a href="d0a7c09304
"><code>d0a7c09</code></a> Don't use SYMLINK_NOFOLLOW in a statat call</li> <li><a href="940c163242
"><code>940c163</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/eminence/procfs/issues/248">#248</a> from eminence/criterion_update</li> <li><a href="0e31f6c8ee
"><code>0e31f6c</code></a> Update criterion dev-depencency</li> <li>Additional commits viewable in <a href="https://github.com/eminence/procfs/compare/v0.14.1...v0.15.1">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
218 lines
6.1 KiB
Rust
218 lines
6.1 KiB
Rust
use log::info;
|
|
use procfs::process::{FDInfo, Io, Process, Stat, Status};
|
|
use procfs::{ProcError, ProcessCgroup};
|
|
use std::thread;
|
|
use std::time::{Duration, Instant};
|
|
|
|
pub enum ProcessTask {
|
|
Process(Process),
|
|
Task { stat: Box<Stat>, owner: u32 },
|
|
}
|
|
|
|
impl ProcessTask {
|
|
pub fn stat(&self) -> Result<Stat, ProcError> {
|
|
match self {
|
|
ProcessTask::Process(x) => x.stat(),
|
|
ProcessTask::Task { stat: x, owner: _ } => Ok(*x.clone()),
|
|
}
|
|
}
|
|
|
|
pub fn cmdline(&self) -> Result<Vec<String>, ProcError> {
|
|
match self {
|
|
ProcessTask::Process(x) => x.cmdline(),
|
|
_ => Err(ProcError::Other("not supported".to_string())),
|
|
}
|
|
}
|
|
|
|
pub fn cgroups(&self) -> Result<Vec<ProcessCgroup>, ProcError> {
|
|
match self {
|
|
ProcessTask::Process(x) => x.cgroups(),
|
|
_ => Err(ProcError::Other("not supported".to_string())),
|
|
}
|
|
}
|
|
|
|
pub fn fd(&self) -> Result<Vec<FDInfo>, ProcError> {
|
|
match self {
|
|
ProcessTask::Process(x) => x.fd()?.collect(),
|
|
_ => Err(ProcError::Other("not supported".to_string())),
|
|
}
|
|
}
|
|
|
|
pub fn loginuid(&self) -> Result<u32, ProcError> {
|
|
match self {
|
|
ProcessTask::Process(x) => x.loginuid(),
|
|
_ => Err(ProcError::Other("not supported".to_string())),
|
|
}
|
|
}
|
|
|
|
pub fn owner(&self) -> u32 {
|
|
match self {
|
|
ProcessTask::Process(x) => x.uid().unwrap_or(0),
|
|
ProcessTask::Task { stat: _, owner: x } => *x,
|
|
}
|
|
}
|
|
|
|
pub fn wchan(&self) -> Result<String, ProcError> {
|
|
match self {
|
|
ProcessTask::Process(x) => x.wchan(),
|
|
_ => Err(ProcError::Other("not supported".to_string())),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct ProcessInfo {
|
|
pub pid: i32,
|
|
pub ppid: i32,
|
|
pub curr_proc: ProcessTask,
|
|
pub curr_io: Option<Io>,
|
|
pub prev_io: Option<Io>,
|
|
pub curr_stat: Option<Stat>,
|
|
pub prev_stat: Option<Stat>,
|
|
pub curr_status: Option<Status>,
|
|
pub interval: Duration,
|
|
}
|
|
|
|
pub fn collect_proc(interval: Duration, _with_thread: bool) -> Vec<ProcessInfo> {
|
|
let mut base_procs = Vec::new();
|
|
let mut ret = Vec::new();
|
|
|
|
// Take an initial snapshot of process I/O and CPU info, so we can calculate changes over time
|
|
if let Ok(all_proc) = procfs::process::all_processes() {
|
|
for proc in all_proc.flatten() {
|
|
let io = proc.io().ok();
|
|
let stat = proc.stat().ok();
|
|
let time = Instant::now();
|
|
base_procs.push((proc.pid(), io, stat, time));
|
|
}
|
|
}
|
|
|
|
// wait a bit...
|
|
thread::sleep(interval);
|
|
|
|
// now get process info again, build up results
|
|
for (pid, prev_io, prev_stat, prev_time) in base_procs {
|
|
let curr_proc_pid = pid;
|
|
let curr_proc = if let Ok(p) = Process::new(curr_proc_pid) {
|
|
p
|
|
} else {
|
|
info!("failed to retrieve info for pid={curr_proc_pid}, process probably died between snapshots");
|
|
continue;
|
|
};
|
|
|
|
let curr_io = curr_proc.io().ok();
|
|
let curr_stat = curr_proc.stat().ok();
|
|
let curr_status = curr_proc.status().ok();
|
|
let curr_time = Instant::now();
|
|
let interval = curr_time - prev_time;
|
|
let ppid = curr_proc.stat().map(|p| p.ppid).unwrap_or_default();
|
|
let curr_proc = ProcessTask::Process(curr_proc);
|
|
|
|
let proc = ProcessInfo {
|
|
pid,
|
|
ppid,
|
|
curr_proc,
|
|
curr_io,
|
|
prev_io,
|
|
curr_stat,
|
|
prev_stat,
|
|
curr_status,
|
|
interval,
|
|
};
|
|
|
|
ret.push(proc);
|
|
}
|
|
|
|
ret
|
|
}
|
|
|
|
impl ProcessInfo {
|
|
/// PID of process
|
|
pub fn pid(&self) -> i32 {
|
|
self.pid
|
|
}
|
|
|
|
/// Name of command
|
|
pub fn name(&self) -> String {
|
|
self.command()
|
|
.split(' ')
|
|
.collect::<Vec<_>>()
|
|
.first()
|
|
.map(|x| x.to_string())
|
|
.unwrap_or_default()
|
|
}
|
|
|
|
/// Full name of command, with arguments
|
|
pub fn command(&self) -> String {
|
|
if let Ok(cmd) = &self.curr_proc.cmdline() {
|
|
if !cmd.is_empty() {
|
|
cmd.join(" ").replace(['\n', '\t'], " ")
|
|
} else {
|
|
match self.curr_proc.stat() {
|
|
Ok(p) => p.comm,
|
|
Err(_) => "".to_string(),
|
|
}
|
|
}
|
|
} else {
|
|
match self.curr_proc.stat() {
|
|
Ok(p) => p.comm,
|
|
Err(_) => "".to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Get the status of the process
|
|
pub fn status(&self) -> String {
|
|
if let Ok(p) = self.curr_proc.stat() {
|
|
match p.state {
|
|
'S' => "Sleeping",
|
|
'R' => "Running",
|
|
'D' => "Disk sleep",
|
|
'Z' => "Zombie",
|
|
'T' => "Stopped",
|
|
't' => "Tracing",
|
|
'X' => "Dead",
|
|
'x' => "Dead",
|
|
'K' => "Wakekill",
|
|
'W' => "Waking",
|
|
'P' => "Parked",
|
|
_ => "Unknown",
|
|
}
|
|
} else {
|
|
"Unknown"
|
|
}
|
|
.into()
|
|
}
|
|
|
|
/// CPU usage as a percent of total
|
|
pub fn cpu_usage(&self) -> f64 {
|
|
if let Some(cs) = &self.curr_stat {
|
|
if let Some(ps) = &self.prev_stat {
|
|
let curr_time = cs.utime + cs.stime;
|
|
let prev_time = ps.utime + ps.stime;
|
|
|
|
let usage_ms = (curr_time - prev_time) * 1000 / procfs::ticks_per_second();
|
|
let interval_ms =
|
|
self.interval.as_secs() * 1000 + u64::from(self.interval.subsec_millis());
|
|
usage_ms as f64 * 100.0 / interval_ms as f64
|
|
} else {
|
|
0.0
|
|
}
|
|
} else {
|
|
0.0
|
|
}
|
|
}
|
|
|
|
/// Memory size in number of bytes
|
|
pub fn mem_size(&self) -> u64 {
|
|
match self.curr_proc.stat() {
|
|
Ok(p) => p.rss_bytes(),
|
|
Err(_) => 0,
|
|
}
|
|
}
|
|
|
|
/// Virtual memory size in bytes
|
|
pub fn virtual_size(&self) -> u64 {
|
|
self.curr_proc.stat().map(|p| p.vsize).unwrap_or_default()
|
|
}
|
|
}
|