Merge pull request #1513 from sylvestre/uptime-since

feature(uptime): add option --since
This commit is contained in:
Sylvestre Ledru 2020-05-21 22:18:52 +02:00 committed by GitHub
commit 817a237821
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 37 deletions

2
Cargo.lock generated
View file

@ -1911,6 +1911,8 @@ dependencies = [
name = "uptime"
version = "0.0.1"
dependencies = [
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"uucore 0.0.2 (git+https://github.com/uutils/uucore/?tag=0.0.2)",

View file

@ -12,6 +12,8 @@ path = "src/uptime.rs"
[dependencies]
getopts = "0.2.18"
time = "0.1.40"
chrono = "0.4"
clap = "2.32"
uucore = { version = "0.0.2", features = ["utmpx"] }
[[bin]]

View file

@ -12,19 +12,24 @@
/* last synced with: cat (GNU coreutils) 8.13 */
extern crate getopts;
extern crate chrono;
extern crate clap;
extern crate time;
use chrono::{Local, TimeZone, Utc};
use clap::{App, Arg};
#[macro_use]
extern crate uucore;
// import crate time from utmpx
pub use uucore::libc;
use uucore::libc::time_t;
use getopts::Options;
static NAME: &str = "uptime";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "Display the current time, the length of time the system has been up,\n\
the number of users on the system, and the average number of jobs\n\
in the run queue over the last 1, 5 and 15 minutes.";
static OPT_SINCE: &str = "SINCE";
#[cfg(unix)]
use libc::getloadavg;
@ -34,38 +39,24 @@ extern "C" {
fn GetTickCount() -> libc::uint32_t;
}
fn get_usage() -> String {
format!("{0} [OPTION]...", executable!())
}
pub fn uumain(args: Vec<String>) -> i32 {
let mut opts = Options::new();
let usage = get_usage();
let matches = App::new(executable!())
.version(VERSION)
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_SINCE)
.short("s")
.long("since")
.help("system up since"),
)
.get_matches_from(&args);
opts.optflag("v", "version", "output version information and exit");
opts.optflag("h", "help", "display this help and exit");
let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(f) => crash!(1, "Invalid options\n{}", f),
};
if matches.opt_present("version") {
println!("{} {}", NAME, VERSION);
return 0;
}
if matches.opt_present("help") || !matches.free.is_empty() {
println!("{} {}", NAME, VERSION);
println!();
println!("Usage:");
println!(" {0} [OPTION]", NAME);
println!();
println!(
"{}",
opts.usage(
"Print the current time, the length of time the system has been up,\n\
the number of users on the system, and the average number of jobs\n\
in the run queue over the last 1, 5 and 15 minutes."
)
);
return 0;
}
print_time();
let (boot_time, user_count) = process_utmpx();
let uptime = get_uptime(boot_time);
if uptime < 0 {
@ -73,7 +64,14 @@ pub fn uumain(args: Vec<String>) -> i32 {
1
} else {
let upsecs = uptime / 100;
if matches.is_present(OPT_SINCE) {
let initial_date = Local.timestamp(Utc::now().timestamp() - uptime, 0);
println!("{}", initial_date.format("%Y-%m-%d %H:%M:%S"));
return 0;
}
print_time();
let upsecs = uptime;
print_uptime(upsecs);
print_nusers(user_count);
print_loadavg();
@ -164,7 +162,7 @@ fn get_uptime(boot_time: Option<time_t>) -> i64 {
.ok()
.and_then(|mut f| f.read_to_string(&mut proc_uptime).ok())
.and_then(|_| proc_uptime.split_whitespace().next())
.and_then(|s| s.replace(".", "").parse().ok())
.and_then(|s| s.split('.').next().unwrap_or("0").parse().ok())
{
n
} else {
@ -172,7 +170,7 @@ fn get_uptime(boot_time: Option<time_t>) -> i64 {
Some(t) => {
let now = time::get_time().sec;
let boottime = t as i64;
(now - boottime) * 100
now - boottime
}
_ => -1,
}

View file

@ -1,3 +1,5 @@
extern crate regex;
use self::regex::Regex;
use common::util::*;
#[test]
@ -12,3 +14,17 @@ fn test_uptime() {
assert!(result.stdout.contains(" up "));
// Don't check for users as it doesn't show in some CI
}
#[test]
fn test_uptime_since() {
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("--since").succeeds();
println!("stdout = {}", result.stdout);
println!("stderr = {}", result.stderr);
assert!(result.success);
let re = Regex::new(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}").unwrap();
assert!(re.is_match(&result.stdout.trim()));
}