diff --git a/Cargo.lock b/Cargo.lock index b005441edf..4bbde8fc31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2381,6 +2381,7 @@ dependencies = [ "nu-glob", "nu-path", "nu-protocol", + "sysinfo", ] [[package]] diff --git a/crates/nu-command/src/system/sys.rs b/crates/nu-command/src/system/sys.rs index 3750d9f7c8..70cc927658 100644 --- a/crates/nu-command/src/system/sys.rs +++ b/crates/nu-command/src/system/sys.rs @@ -1,8 +1,11 @@ +use chrono::prelude::DateTime; +use chrono::Local; use nu_protocol::{ ast::Call, engine::{Command, EngineState, Stack}, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value, }; +use std::time::{Duration, UNIX_EPOCH}; use sysinfo::{ComponentExt, DiskExt, NetworkExt, ProcessorExt, System, SystemExt, UserExt}; #[derive(Clone)] @@ -135,6 +138,18 @@ pub fn disks(sys: &mut System, span: Span) -> Option { span, }); + cols.push("removable".into()); + vals.push(Value::Bool { + val: disk.is_removable(), + span, + }); + + cols.push("removable".into()); + vals.push(Value::String { + val: format!("{:?}", disk.type_()), + span, + }); + output.push(Value::Record { cols, vals, span }); } if !output.is_empty() { @@ -206,8 +221,37 @@ pub fn cpu(sys: &mut System, span: Span) -> Option { span, }); + cols.push("cpu_usage".into()); + vals.push(Value::Float { + val: cpu.cpu_usage() as f64, + span, + }); + + let load_avg = sys.load_average(); + cols.push("load_average".into()); + vals.push(Value::String { + val: trim_cstyle_null(format!( + "{:.2}, {:.2}, {:.2}", + load_avg.one, load_avg.five, load_avg.fifteen + )), + span, + }); + + cols.push("vendor_id".into()); + vals.push(Value::String { + val: trim_cstyle_null(cpu.vendor_id().to_string()), + span, + }); + + cols.push("freq".into()); + vals.push(Value::Int { + val: sys.physical_core_count().unwrap_or(0) as i64, + span, + }); + output.push(Value::Record { cols, vals, span }); } + if !output.is_empty() { Some(Value::List { vals: output, span }) } else { @@ -223,8 +267,12 @@ pub fn mem(sys: &mut System, span: Span) -> Option { let total_mem = sys.total_memory(); let free_mem = sys.free_memory(); + let used_mem = sys.used_memory(); + let avail_mem = sys.available_memory(); + let total_swap = sys.total_swap(); let free_swap = sys.free_swap(); + let used_swap = sys.used_swap(); cols.push("total".into()); vals.push(Value::Filesize { @@ -238,6 +286,18 @@ pub fn mem(sys: &mut System, span: Span) -> Option { span, }); + cols.push("used".into()); + vals.push(Value::Filesize { + val: used_mem as i64 * 1000, + span, + }); + + cols.push("available".into()); + vals.push(Value::Filesize { + val: avail_mem as i64 * 1000, + span, + }); + cols.push("swap total".into()); vals.push(Value::Filesize { val: total_swap as i64 * 1000, @@ -250,6 +310,12 @@ pub fn mem(sys: &mut System, span: Span) -> Option { span, }); + cols.push("swap used".into()); + vals.push(Value::Filesize { + val: used_swap as i64 * 1000, + span, + }); + Some(Value::Record { cols, vals, span }) } @@ -267,14 +333,23 @@ pub fn host(sys: &mut System, span: Span) -> Option { }); } if let Some(version) = sys.os_version() { - cols.push("os version".into()); + cols.push("os_version".into()); vals.push(Value::String { val: trim_cstyle_null(version), span, }); } + + if let Some(long_version) = sys.long_os_version() { + cols.push("long_os_version".into()); + vals.push(Value::String { + val: trim_cstyle_null(long_version), + span, + }); + } + if let Some(version) = sys.kernel_version() { - cols.push("kernel version".into()); + cols.push("kernel_version".into()); vals.push(Value::String { val: trim_cstyle_null(version), span, @@ -287,12 +362,26 @@ pub fn host(sys: &mut System, span: Span) -> Option { span, }); } + cols.push("uptime".into()); vals.push(Value::Duration { val: 1000000000 * sys.uptime() as i64, span, }); + // Creates a new SystemTime from the specified number of whole seconds + let d = UNIX_EPOCH + Duration::from_secs(sys.boot_time()); + // Create DateTime from SystemTime + let datetime = DateTime::::from(d); + // Convert to local time and then rfc3339 + let timestamp_str = datetime.with_timezone(datetime.offset()).to_rfc3339(); + + cols.push("boot_time".into()); + vals.push(Value::String { + val: timestamp_str, + span, + }); + let mut users = vec![]; for user in sys.users() { let mut cols = vec![]; @@ -317,6 +406,7 @@ pub fn host(sys: &mut System, span: Span) -> Option { users.push(Value::Record { cols, vals, span }); } + if !users.is_empty() { cols.push("sessions".into()); vals.push(Value::List { vals: users, span }); @@ -362,6 +452,7 @@ pub fn temp(sys: &mut System, span: Span) -> Option { } output.push(Value::Record { cols, vals, span }); } + if !output.is_empty() { Some(Value::List { vals: output, span }) } else { diff --git a/crates/nu-engine/Cargo.toml b/crates/nu-engine/Cargo.toml index a033d0d74b..809129016b 100644 --- a/crates/nu-engine/Cargo.toml +++ b/crates/nu-engine/Cargo.toml @@ -12,6 +12,7 @@ nu-path = { path = "../nu-path", version = "0.61.1" } nu-glob = { path = "../nu-glob", version = "0.61.1" } chrono = { version="0.4.19", features=["serde"] } +sysinfo = "0.23.10" [features] plugin = [] diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index c04aace2d2..75dadae108 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1,7 +1,4 @@ -use std::cmp::Ordering; -use std::collections::HashMap; -use std::io::Write; - +use crate::{current_dir_str, get_full_help}; use nu_path::expand_path_with; use nu_protocol::ast::{Block, Call, Expr, Expression, Operator}; use nu_protocol::engine::{EngineState, Stack, Visibility}; @@ -9,8 +6,10 @@ use nu_protocol::{ IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Range, ShellError, Span, Spanned, SyntaxShape, Unit, Value, VarId, ENV_VARIABLE_ID, }; - -use crate::{current_dir_str, get_full_help}; +use std::cmp::Ordering; +use std::collections::HashMap; +use std::io::Write; +use sysinfo::SystemExt; pub fn eval_operator(op: &Expression) -> Result { match op { @@ -1265,12 +1264,24 @@ pub fn eval_variable( output_cols.push("pid".into()); output_vals.push(Value::int(pid as i64, span)); + let sys = sysinfo::System::new(); + let ver = match sys.kernel_version() { + Some(v) => v, + None => "unknown".into(), + }; + let os_record = Value::Record { - cols: vec!["name".into(), "arch".into(), "family".into()], + cols: vec![ + "name".into(), + "arch".into(), + "family".into(), + "kernel_version".into(), + ], vals: vec![ Value::string(std::env::consts::OS, span), Value::string(std::env::consts::ARCH, span), Value::string(std::env::consts::FAMILY, span), + Value::string(ver, span), ], span, };