nushell/crates/nu-system/src/linux.rs
dependabot[bot] c358400351
Bump procfs from 0.14.1 to 0.15.1 (#8233)
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 />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=procfs&package-manager=cargo&previous-version=0.14.1&new-version=0.15.1)](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>
2023-02-27 20:53:01 +13:00

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()
}
}