Skip to main content

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 is_const(&self) -> bool {
26        true
27    }
28
29    fn run(
30        &self,
31        _engine_state: &EngineState,
32        _stack: &mut Stack,
33        call: &Call,
34        _input: PipelineData,
35    ) -> Result<PipelineData, ShellError> {
36        Ok(host(call.head).into_pipeline_data())
37    }
38
39    fn run_const(
40        &self,
41        _working_set: &StateWorkingSet,
42        call: &Call,
43        _input: PipelineData,
44    ) -> Result<PipelineData, ShellError> {
45        Ok(host(call.head).into_pipeline_data())
46    }
47
48    fn examples(&self) -> Vec<Example<'_>> {
49        vec![Example {
50            description: "Show info about the system host",
51            example: "sys host",
52            result: None,
53        }]
54    }
55}
56
57fn host(span: Span) -> Value {
58    let mut record = Record::new();
59
60    if let Some(name) = System::name() {
61        record.push("name", Value::string(trim_cstyle_null(name), span));
62    }
63    if let Some(version) = System::os_version() {
64        record.push("os_version", Value::string(trim_cstyle_null(version), span));
65    }
66    if let Some(long_version) = System::long_os_version() {
67        record.push(
68            "long_os_version",
69            Value::string(trim_cstyle_null(long_version), span),
70        );
71    }
72    if let Some(version) = System::kernel_version() {
73        record.push(
74            "kernel_version",
75            Value::string(trim_cstyle_null(version), span),
76        );
77    }
78    if let Some(hostname) = System::host_name() {
79        record.push("hostname", Value::string(trim_cstyle_null(hostname), span));
80    }
81
82    let uptime = System::uptime()
83        .saturating_mul(1_000_000_000)
84        .try_into()
85        .unwrap_or(i64::MAX);
86
87    record.push("uptime", Value::duration(uptime, span));
88
89    let boot_time = boot_time()
90        .map(|time| Value::date(time, span))
91        .unwrap_or(Value::nothing(span));
92
93    record.push("boot_time", boot_time);
94
95    Value::record(record, span)
96}
97
98fn boot_time() -> Option<DateTime<FixedOffset>> {
99    // Broken systems can apparently return really high values.
100    // See: https://github.com/nushell/nushell/issues/10155
101    // First, try to convert u64 to i64, and then try to create a `DateTime`.
102    let secs = System::boot_time().try_into().ok()?;
103    let time = DateTime::from_timestamp(secs, 0)?;
104    Some(time.with_timezone(&Local).fixed_offset())
105}