nu_command/system/sys/
host.rs

1use super::trim_cstyle_null;
2use chrono::{DateTime, FixedOffset, Local};
3use nu_engine::command_prelude::*;
4use sysinfo::System;
5
6#[derive(Clone)]
7pub struct SysHost;
8
9impl Command for SysHost {
10    fn name(&self) -> &str {
11        "sys host"
12    }
13
14    fn signature(&self) -> Signature {
15        Signature::build("sys host")
16            .filter()
17            .category(Category::System)
18            .input_output_types(vec![(Type::Nothing, Type::record())])
19    }
20
21    fn description(&self) -> &str {
22        "View information about the system host."
23    }
24
25    fn run(
26        &self,
27        _engine_state: &EngineState,
28        _stack: &mut Stack,
29        call: &Call,
30        _input: PipelineData,
31    ) -> Result<PipelineData, ShellError> {
32        Ok(host(call.head).into_pipeline_data())
33    }
34
35    fn examples(&self) -> Vec<Example> {
36        vec![Example {
37            description: "Show info about the system host",
38            example: "sys host",
39            result: None,
40        }]
41    }
42}
43
44fn host(span: Span) -> Value {
45    let mut record = Record::new();
46
47    if let Some(name) = System::name() {
48        record.push("name", Value::string(trim_cstyle_null(name), span));
49    }
50    if let Some(version) = System::os_version() {
51        record.push("os_version", Value::string(trim_cstyle_null(version), span));
52    }
53    if let Some(long_version) = System::long_os_version() {
54        record.push(
55            "long_os_version",
56            Value::string(trim_cstyle_null(long_version), span),
57        );
58    }
59    if let Some(version) = System::kernel_version() {
60        record.push(
61            "kernel_version",
62            Value::string(trim_cstyle_null(version), span),
63        );
64    }
65    if let Some(hostname) = System::host_name() {
66        record.push("hostname", Value::string(trim_cstyle_null(hostname), span));
67    }
68
69    let uptime = System::uptime()
70        .saturating_mul(1_000_000_000)
71        .try_into()
72        .unwrap_or(i64::MAX);
73
74    record.push("uptime", Value::duration(uptime, span));
75
76    let boot_time = boot_time()
77        .map(|time| Value::date(time, span))
78        .unwrap_or(Value::nothing(span));
79
80    record.push("boot_time", boot_time);
81
82    Value::record(record, span)
83}
84
85fn boot_time() -> Option<DateTime<FixedOffset>> {
86    // Broken systems can apparently return really high values.
87    // See: https://github.com/nushell/nushell/issues/10155
88    // First, try to convert u64 to i64, and then try to create a `DateTime`.
89    let secs = System::boot_time().try_into().ok()?;
90    let time = DateTime::from_timestamp(secs, 0)?;
91    Some(time.with_timezone(&Local).fixed_offset())
92}