2023-09-08 17:24:29 +00:00
|
|
|
#[cfg(windows)]
|
|
|
|
use itertools::Itertools;
|
2024-01-11 15:19:48 +00:00
|
|
|
use nu_engine::CallExt;
|
2023-09-12 19:50:05 +00:00
|
|
|
#[cfg(all(
|
|
|
|
unix,
|
|
|
|
not(target_os = "macos"),
|
|
|
|
not(target_os = "windows"),
|
|
|
|
not(target_os = "android"),
|
|
|
|
))]
|
|
|
|
use nu_protocol::Span;
|
2021-10-01 21:53:13 +00:00
|
|
|
use nu_protocol::{
|
|
|
|
ast::Call,
|
2021-10-25 16:58:58 +00:00
|
|
|
engine::{Command, EngineState, Stack},
|
Create `Record` type (#10103)
# Description
This PR creates a new `Record` type to reduce duplicate code and
possibly bugs as well. (This is an edited version of #9648.)
- `Record` implements `FromIterator` and `IntoIterator` and so can be
iterated over or collected into. For example, this helps with
conversions to and from (hash)maps. (Also, no more
`cols.iter().zip(vals)`!)
- `Record` has a `push(col, val)` function to help insure that the
number of columns is equal to the number of values. I caught a few
potential bugs thanks to this (e.g. in the `ls` command).
- Finally, this PR also adds a `record!` macro that helps simplify
record creation. It is used like so:
```rust
record! {
"key1" => some_value,
"key2" => Value::string("text", span),
"key3" => Value::int(optional_int.unwrap_or(0), span),
"key4" => Value::bool(config.setting, span),
}
```
Since macros hinder formatting, etc., the right hand side values should
be relatively short and sweet like the examples above.
Where possible, prefer `record!` or `.collect()` on an iterator instead
of multiple `Record::push`s, since the first two automatically set the
record capacity and do less work overall.
# User-Facing Changes
Besides the changes in `nu-protocol` the only other breaking changes are
to `nu-table::{ExpandedTable::build_map, JustTable::kv_table}`.
2023-08-24 19:50:29 +00:00
|
|
|
Category, Example, IntoInterruptiblePipelineData, PipelineData, Record, ShellError, Signature,
|
|
|
|
Type, Value,
|
2021-10-01 21:53:13 +00:00
|
|
|
};
|
2023-11-20 20:22:35 +00:00
|
|
|
#[cfg(all(
|
|
|
|
unix,
|
|
|
|
not(target_os = "macos"),
|
|
|
|
not(target_os = "windows"),
|
|
|
|
not(target_os = "android"),
|
|
|
|
))]
|
|
|
|
use procfs::WithCurrentSystemInfo;
|
2023-09-12 19:50:05 +00:00
|
|
|
|
2023-09-08 17:24:29 +00:00
|
|
|
use std::time::Duration;
|
2021-10-01 21:53:13 +00:00
|
|
|
|
2021-10-25 04:01:02 +00:00
|
|
|
#[derive(Clone)]
|
2021-10-01 21:53:13 +00:00
|
|
|
pub struct Ps;
|
|
|
|
|
|
|
|
impl Command for Ps {
|
|
|
|
fn name(&self) -> &str {
|
|
|
|
"ps"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signature(&self) -> Signature {
|
|
|
|
Signature::build("ps")
|
2022-12-21 19:20:46 +00:00
|
|
|
.input_output_types(vec![(Type::Nothing, Type::Table(vec![]))])
|
2021-10-01 21:53:13 +00:00
|
|
|
.switch(
|
|
|
|
"long",
|
|
|
|
"list all available columns for each entry",
|
|
|
|
Some('l'),
|
|
|
|
)
|
|
|
|
.filter()
|
2021-11-17 04:22:37 +00:00
|
|
|
.category(Category::System)
|
2021-10-01 21:53:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn usage(&self) -> &str {
|
|
|
|
"View information about system processes."
|
|
|
|
}
|
|
|
|
|
2022-07-21 11:29:41 +00:00
|
|
|
fn search_terms(&self) -> Vec<&str> {
|
|
|
|
vec!["procedures", "operations", "tasks", "ops"]
|
|
|
|
}
|
|
|
|
|
2021-10-01 21:53:13 +00:00
|
|
|
fn run(
|
|
|
|
&self,
|
2021-10-28 04:13:10 +00:00
|
|
|
engine_state: &EngineState,
|
2024-01-11 15:19:48 +00:00
|
|
|
stack: &mut Stack,
|
2021-10-01 21:53:13 +00:00
|
|
|
call: &Call,
|
2021-10-25 04:01:02 +00:00
|
|
|
_input: PipelineData,
|
2023-02-05 21:17:46 +00:00
|
|
|
) -> Result<PipelineData, ShellError> {
|
2024-01-11 15:19:48 +00:00
|
|
|
run_ps(engine_state, stack, call)
|
2021-10-01 21:53:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn examples(&self) -> Vec<Example> {
|
2022-03-04 12:10:09 +00:00
|
|
|
vec![
|
|
|
|
Example {
|
|
|
|
description: "List the system processes",
|
|
|
|
example: "ps",
|
|
|
|
result: None,
|
|
|
|
},
|
|
|
|
Example {
|
|
|
|
description: "List the top 5 system processes with the highest memory usage",
|
|
|
|
example: "ps | sort-by mem | last 5",
|
|
|
|
result: None,
|
|
|
|
},
|
|
|
|
Example {
|
|
|
|
description: "List the top 3 system processes with the highest CPU usage",
|
|
|
|
example: "ps | sort-by cpu | last 3",
|
|
|
|
result: None,
|
|
|
|
},
|
|
|
|
Example {
|
|
|
|
description: "List the system processes with 'nu' in their names",
|
|
|
|
example: "ps | where name =~ 'nu'",
|
|
|
|
result: None,
|
|
|
|
},
|
2023-04-06 12:32:12 +00:00
|
|
|
Example {
|
|
|
|
description: "Get the parent process id of the current nu process",
|
|
|
|
example: "ps | where pid == $nu.pid | get ppid",
|
|
|
|
result: None,
|
|
|
|
},
|
2022-03-04 12:10:09 +00:00
|
|
|
]
|
2021-10-01 21:53:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-11 15:19:48 +00:00
|
|
|
fn run_ps(
|
|
|
|
engine_state: &EngineState,
|
|
|
|
stack: &mut Stack,
|
|
|
|
call: &Call,
|
|
|
|
) -> Result<PipelineData, ShellError> {
|
2022-01-14 06:20:53 +00:00
|
|
|
let mut output = vec![];
|
2021-10-01 21:53:13 +00:00
|
|
|
let span = call.head;
|
2024-01-11 15:19:48 +00:00
|
|
|
let long = call.has_flag(engine_state, stack, "long")?;
|
2021-10-01 21:53:13 +00:00
|
|
|
|
2022-01-14 06:20:53 +00:00
|
|
|
for proc in nu_system::collect_proc(Duration::from_millis(100), false) {
|
Create `Record` type (#10103)
# Description
This PR creates a new `Record` type to reduce duplicate code and
possibly bugs as well. (This is an edited version of #9648.)
- `Record` implements `FromIterator` and `IntoIterator` and so can be
iterated over or collected into. For example, this helps with
conversions to and from (hash)maps. (Also, no more
`cols.iter().zip(vals)`!)
- `Record` has a `push(col, val)` function to help insure that the
number of columns is equal to the number of values. I caught a few
potential bugs thanks to this (e.g. in the `ls` command).
- Finally, this PR also adds a `record!` macro that helps simplify
record creation. It is used like so:
```rust
record! {
"key1" => some_value,
"key2" => Value::string("text", span),
"key3" => Value::int(optional_int.unwrap_or(0), span),
"key4" => Value::bool(config.setting, span),
}
```
Since macros hinder formatting, etc., the right hand side values should
be relatively short and sweet like the examples above.
Where possible, prefer `record!` or `.collect()` on an iterator instead
of multiple `Record::push`s, since the first two automatically set the
record capacity and do less work overall.
# User-Facing Changes
Besides the changes in `nu-protocol` the only other breaking changes are
to `nu-table::{ExpandedTable::build_map, JustTable::kv_table}`.
2023-08-24 19:50:29 +00:00
|
|
|
let mut record = Record::new();
|
|
|
|
|
|
|
|
record.push("pid", Value::int(proc.pid() as i64, span));
|
|
|
|
record.push("ppid", Value::int(proc.ppid() as i64, span));
|
|
|
|
record.push("name", Value::string(proc.name(), span));
|
2022-01-14 06:20:53 +00:00
|
|
|
|
2022-01-15 19:44:24 +00:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
{
|
|
|
|
// Hide status on Windows until we can find a good way to support it
|
Create `Record` type (#10103)
# Description
This PR creates a new `Record` type to reduce duplicate code and
possibly bugs as well. (This is an edited version of #9648.)
- `Record` implements `FromIterator` and `IntoIterator` and so can be
iterated over or collected into. For example, this helps with
conversions to and from (hash)maps. (Also, no more
`cols.iter().zip(vals)`!)
- `Record` has a `push(col, val)` function to help insure that the
number of columns is equal to the number of values. I caught a few
potential bugs thanks to this (e.g. in the `ls` command).
- Finally, this PR also adds a `record!` macro that helps simplify
record creation. It is used like so:
```rust
record! {
"key1" => some_value,
"key2" => Value::string("text", span),
"key3" => Value::int(optional_int.unwrap_or(0), span),
"key4" => Value::bool(config.setting, span),
}
```
Since macros hinder formatting, etc., the right hand side values should
be relatively short and sweet like the examples above.
Where possible, prefer `record!` or `.collect()` on an iterator instead
of multiple `Record::push`s, since the first two automatically set the
record capacity and do less work overall.
# User-Facing Changes
Besides the changes in `nu-protocol` the only other breaking changes are
to `nu-table::{ExpandedTable::build_map, JustTable::kv_table}`.
2023-08-24 19:50:29 +00:00
|
|
|
record.push("status", Value::string(proc.status(), span));
|
2022-01-15 19:44:24 +00:00
|
|
|
}
|
2022-01-14 06:20:53 +00:00
|
|
|
|
Create `Record` type (#10103)
# Description
This PR creates a new `Record` type to reduce duplicate code and
possibly bugs as well. (This is an edited version of #9648.)
- `Record` implements `FromIterator` and `IntoIterator` and so can be
iterated over or collected into. For example, this helps with
conversions to and from (hash)maps. (Also, no more
`cols.iter().zip(vals)`!)
- `Record` has a `push(col, val)` function to help insure that the
number of columns is equal to the number of values. I caught a few
potential bugs thanks to this (e.g. in the `ls` command).
- Finally, this PR also adds a `record!` macro that helps simplify
record creation. It is used like so:
```rust
record! {
"key1" => some_value,
"key2" => Value::string("text", span),
"key3" => Value::int(optional_int.unwrap_or(0), span),
"key4" => Value::bool(config.setting, span),
}
```
Since macros hinder formatting, etc., the right hand side values should
be relatively short and sweet like the examples above.
Where possible, prefer `record!` or `.collect()` on an iterator instead
of multiple `Record::push`s, since the first two automatically set the
record capacity and do less work overall.
# User-Facing Changes
Besides the changes in `nu-protocol` the only other breaking changes are
to `nu-table::{ExpandedTable::build_map, JustTable::kv_table}`.
2023-08-24 19:50:29 +00:00
|
|
|
record.push("cpu", Value::float(proc.cpu_usage(), span));
|
|
|
|
record.push("mem", Value::filesize(proc.mem_size() as i64, span));
|
|
|
|
record.push("virtual", Value::filesize(proc.virtual_size() as i64, span));
|
2022-01-14 06:20:53 +00:00
|
|
|
|
|
|
|
if long {
|
Create `Record` type (#10103)
# Description
This PR creates a new `Record` type to reduce duplicate code and
possibly bugs as well. (This is an edited version of #9648.)
- `Record` implements `FromIterator` and `IntoIterator` and so can be
iterated over or collected into. For example, this helps with
conversions to and from (hash)maps. (Also, no more
`cols.iter().zip(vals)`!)
- `Record` has a `push(col, val)` function to help insure that the
number of columns is equal to the number of values. I caught a few
potential bugs thanks to this (e.g. in the `ls` command).
- Finally, this PR also adds a `record!` macro that helps simplify
record creation. It is used like so:
```rust
record! {
"key1" => some_value,
"key2" => Value::string("text", span),
"key3" => Value::int(optional_int.unwrap_or(0), span),
"key4" => Value::bool(config.setting, span),
}
```
Since macros hinder formatting, etc., the right hand side values should
be relatively short and sweet like the examples above.
Where possible, prefer `record!` or `.collect()` on an iterator instead
of multiple `Record::push`s, since the first two automatically set the
record capacity and do less work overall.
# User-Facing Changes
Besides the changes in `nu-protocol` the only other breaking changes are
to `nu-table::{ExpandedTable::build_map, JustTable::kv_table}`.
2023-08-24 19:50:29 +00:00
|
|
|
record.push("command", Value::string(proc.command(), span));
|
2023-09-12 19:50:05 +00:00
|
|
|
#[cfg(all(
|
|
|
|
unix,
|
|
|
|
not(target_os = "macos"),
|
|
|
|
not(target_os = "windows"),
|
|
|
|
not(target_os = "android"),
|
|
|
|
))]
|
|
|
|
{
|
2023-12-06 23:40:03 +00:00
|
|
|
let proc_stat = proc
|
|
|
|
.curr_proc
|
|
|
|
.stat()
|
|
|
|
.map_err(|e| ShellError::GenericError {
|
|
|
|
error: "Error getting process stat".into(),
|
|
|
|
msg: e.to_string(),
|
|
|
|
span: Some(Span::unknown()),
|
|
|
|
help: None,
|
|
|
|
inner: vec![],
|
|
|
|
})?;
|
2023-11-20 20:22:35 +00:00
|
|
|
// If we can't get the start time, just use the current time
|
|
|
|
let proc_start = proc_stat
|
|
|
|
.starttime()
|
|
|
|
.get()
|
|
|
|
.unwrap_or_else(|_| chrono::Local::now());
|
2023-09-12 19:50:05 +00:00
|
|
|
record.push("start_time", Value::date(proc_start.into(), span));
|
|
|
|
record.push("user_id", Value::int(proc.curr_proc.owner() as i64, span));
|
|
|
|
// These work and may be helpful, but it just seemed crowded
|
|
|
|
// record.push("group_id", Value::int(proc_stat.pgrp as i64, span));
|
|
|
|
// record.push("session_id", Value::int(proc_stat.session as i64, span));
|
|
|
|
// This may be helpful for ctrl+z type of checking, once we get there
|
|
|
|
// record.push("tpg_id", Value::int(proc_stat.tpgid as i64, span));
|
|
|
|
record.push("priority", Value::int(proc_stat.priority, span));
|
|
|
|
record.push("process_threads", Value::int(proc_stat.num_threads, span));
|
2023-09-14 13:10:15 +00:00
|
|
|
record.push("cwd", Value::string(proc.cwd(), span));
|
2023-09-12 19:50:05 +00:00
|
|
|
}
|
2022-02-01 21:05:26 +00:00
|
|
|
#[cfg(windows)]
|
|
|
|
{
|
2023-09-08 17:24:29 +00:00
|
|
|
//TODO: There's still more information we can cram in there if we want to
|
|
|
|
// see the ProcessInfo struct for more information
|
|
|
|
record.push(
|
|
|
|
"start_time",
|
|
|
|
Value::date(proc.start_time.fixed_offset(), span),
|
|
|
|
);
|
|
|
|
record.push(
|
|
|
|
"user",
|
|
|
|
Value::string(
|
|
|
|
proc.user.clone().name.unwrap_or("unknown".to_string()),
|
|
|
|
span,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
record.push(
|
|
|
|
"user_sid",
|
|
|
|
Value::string(
|
|
|
|
proc.user
|
|
|
|
.clone()
|
|
|
|
.sid
|
|
|
|
.iter()
|
|
|
|
.map(|r| r.to_string())
|
|
|
|
.join("-"),
|
|
|
|
span,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
record.push("priority", Value::int(proc.priority as i64, span));
|
Create `Record` type (#10103)
# Description
This PR creates a new `Record` type to reduce duplicate code and
possibly bugs as well. (This is an edited version of #9648.)
- `Record` implements `FromIterator` and `IntoIterator` and so can be
iterated over or collected into. For example, this helps with
conversions to and from (hash)maps. (Also, no more
`cols.iter().zip(vals)`!)
- `Record` has a `push(col, val)` function to help insure that the
number of columns is equal to the number of values. I caught a few
potential bugs thanks to this (e.g. in the `ls` command).
- Finally, this PR also adds a `record!` macro that helps simplify
record creation. It is used like so:
```rust
record! {
"key1" => some_value,
"key2" => Value::string("text", span),
"key3" => Value::int(optional_int.unwrap_or(0), span),
"key4" => Value::bool(config.setting, span),
}
```
Since macros hinder formatting, etc., the right hand side values should
be relatively short and sweet like the examples above.
Where possible, prefer `record!` or `.collect()` on an iterator instead
of multiple `Record::push`s, since the first two automatically set the
record capacity and do less work overall.
# User-Facing Changes
Besides the changes in `nu-protocol` the only other breaking changes are
to `nu-table::{ExpandedTable::build_map, JustTable::kv_table}`.
2023-08-24 19:50:29 +00:00
|
|
|
record.push("cwd", Value::string(proc.cwd(), span));
|
|
|
|
record.push(
|
|
|
|
"environment",
|
|
|
|
Value::list(
|
|
|
|
proc.environ()
|
|
|
|
.iter()
|
|
|
|
.map(|x| Value::string(x.to_string(), span))
|
|
|
|
.collect(),
|
|
|
|
span,
|
|
|
|
),
|
|
|
|
);
|
2022-02-01 21:05:26 +00:00
|
|
|
}
|
2023-09-14 13:10:15 +00:00
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
{
|
|
|
|
record.push("cwd", Value::string(proc.cwd(), span));
|
|
|
|
}
|
2021-10-01 21:53:13 +00:00
|
|
|
}
|
2022-01-14 06:20:53 +00:00
|
|
|
|
Create `Record` type (#10103)
# Description
This PR creates a new `Record` type to reduce duplicate code and
possibly bugs as well. (This is an edited version of #9648.)
- `Record` implements `FromIterator` and `IntoIterator` and so can be
iterated over or collected into. For example, this helps with
conversions to and from (hash)maps. (Also, no more
`cols.iter().zip(vals)`!)
- `Record` has a `push(col, val)` function to help insure that the
number of columns is equal to the number of values. I caught a few
potential bugs thanks to this (e.g. in the `ls` command).
- Finally, this PR also adds a `record!` macro that helps simplify
record creation. It is used like so:
```rust
record! {
"key1" => some_value,
"key2" => Value::string("text", span),
"key3" => Value::int(optional_int.unwrap_or(0), span),
"key4" => Value::bool(config.setting, span),
}
```
Since macros hinder formatting, etc., the right hand side values should
be relatively short and sweet like the examples above.
Where possible, prefer `record!` or `.collect()` on an iterator instead
of multiple `Record::push`s, since the first two automatically set the
record capacity and do less work overall.
# User-Facing Changes
Besides the changes in `nu-protocol` the only other breaking changes are
to `nu-table::{ExpandedTable::build_map, JustTable::kv_table}`.
2023-08-24 19:50:29 +00:00
|
|
|
output.push(Value::record(record, span));
|
2021-10-01 21:53:13 +00:00
|
|
|
}
|
|
|
|
|
2021-10-28 04:13:10 +00:00
|
|
|
Ok(output
|
|
|
|
.into_iter()
|
|
|
|
.into_pipeline_data(engine_state.ctrlc.clone()))
|
2021-10-01 21:53:13 +00:00
|
|
|
}
|