mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
uptime: Add -p, --pretty argument (#10143)
* uptime: Add -p, --pretty argument Rebase of PR https://github.com/uutils/coreutils/pull/7910 All credits go to GitHub User: https://github.com/irbeam256 * Add localization for "up"
This commit is contained in:
@@ -184,7 +184,9 @@ also provides a `-v`/`--verbose` flag.
|
||||
|
||||
## `uptime`
|
||||
|
||||
Similar to the proc-ps implementation and unlike GNU/Coreutils, `uptime` provides `-s`/`--since` to show since when the system is up.
|
||||
Similar to the proc-ps implementation and unlike GNU/Coreutils, `uptime` provides:
|
||||
* `-s`/`--since` to show since when the system is up
|
||||
* `-p`/`--pretty` to display uptime in a pretty-printed format
|
||||
|
||||
## `base32/base64/basenc`
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ uptime-about-musl-warning = Warning: When built with musl libc, the `uptime` uti
|
||||
# Help messages
|
||||
uptime-help-since = system up since
|
||||
uptime-help-path = file to search boot time from
|
||||
uptime-help-pretty = show uptime in pretty format
|
||||
|
||||
# Error messages
|
||||
uptime-error-io = couldn't get boot time: { $error }
|
||||
@@ -18,6 +19,7 @@ uptime-error-couldnt-get-boot-time = couldn't get boot time
|
||||
|
||||
# Output messages
|
||||
uptime-output-unknown-uptime = up ???? days ??:??,
|
||||
uptime-output-up-text = up
|
||||
|
||||
uptime-user-count = { $count ->
|
||||
[one] 1 user
|
||||
@@ -36,6 +38,18 @@ uptime-format = { $days ->
|
||||
[one] { $days } day, { $time }
|
||||
*[other] { $days } days { $time }
|
||||
}
|
||||
uptime-format-pretty-min = { $min ->
|
||||
[one] { $min } minute
|
||||
*[other] { $min } minutes
|
||||
}
|
||||
uptime-format-pretty-hour = { $hour ->
|
||||
[one] { $hour } hour
|
||||
*[other] { $hour } hours
|
||||
}
|
||||
uptime-format-pretty-day = { $day ->
|
||||
[one] { $day } day
|
||||
*[other] { $day } days
|
||||
}
|
||||
|
||||
# Load average formatting
|
||||
uptime-lib-format-loadavg = load average: { $avg1 }, { $avg5 }, { $avg15 }
|
||||
|
||||
@@ -9,6 +9,7 @@ uptime-about-musl-warning = Avertissement : Lorsque compilé avec musl libc, l'u
|
||||
# Messages d'aide
|
||||
uptime-help-since = système actif depuis
|
||||
uptime-help-path = fichier pour rechercher l'heure de démarrage
|
||||
uptime-help-pretty = afficher le temps de disponibilité dans un format agréable
|
||||
|
||||
# Messages d'erreur
|
||||
uptime-error-io = impossible d'obtenir l'heure de démarrage : { $error }
|
||||
@@ -18,6 +19,7 @@ uptime-error-couldnt-get-boot-time = impossible d'obtenir l'heure de démarrage
|
||||
|
||||
# Messages de sortie
|
||||
uptime-output-unknown-uptime = actif ???? jours ??:??,
|
||||
uptime-output-up-text = actif
|
||||
|
||||
uptime-user-count = { $count ->
|
||||
[one] 1 utilisateur
|
||||
@@ -36,6 +38,18 @@ uptime-format = { $days ->
|
||||
[one] { $days } jour, { $time }
|
||||
*[other] { $days } jours { $time }
|
||||
}
|
||||
uptime-format-pretty-min = { $min ->
|
||||
[one] { $min } minute
|
||||
*[other] { $min } minutes
|
||||
}
|
||||
uptime-format-pretty-hour = { $hour ->
|
||||
[one] { $hour } heure
|
||||
*[other] { $hour } heures
|
||||
}
|
||||
uptime-format-pretty-day = { $day ->
|
||||
[one] { $day } jour
|
||||
*[other] { $day } jours
|
||||
}
|
||||
|
||||
# Formatage de la charge moyenne
|
||||
uptime-lib-format-loadavg = charge moyenne : { $avg1 }, { $avg5 }, { $avg15 }
|
||||
|
||||
@@ -27,6 +27,7 @@ use uucore::utmpx::*;
|
||||
pub mod options {
|
||||
pub static SINCE: &str = "since";
|
||||
pub static PATH: &str = "path";
|
||||
pub static PRETTY: &str = "pretty";
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -57,6 +58,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
|
||||
if matches.get_flag(options::SINCE) {
|
||||
uptime_since()
|
||||
} else if matches.get_flag(options::PRETTY) {
|
||||
pretty_print_uptime()
|
||||
} else if let Some(path) = file_path {
|
||||
uptime_with_file(path)
|
||||
} else {
|
||||
@@ -92,6 +95,13 @@ pub fn uu_app() -> Command {
|
||||
.value_parser(ValueParser::os_string())
|
||||
.value_hint(ValueHint::AnyPath),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::PRETTY)
|
||||
.short('p')
|
||||
.long(options::PRETTY)
|
||||
.help(translate!("uptime-help-pretty"))
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
@@ -266,6 +276,17 @@ fn print_time() {
|
||||
}
|
||||
|
||||
fn print_uptime(boot_time: Option<time_t>) -> UResult<()> {
|
||||
print!("up {}, ", get_formatted_uptime(boot_time)?);
|
||||
let localized_text = translate!("uptime-output-up-text");
|
||||
let uptime_message = get_formatted_uptime(boot_time, OutputFormat::HumanReadable)?;
|
||||
|
||||
print!("{localized_text} {uptime_message}, ");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pretty_print_uptime() -> UResult<()> {
|
||||
let localized_text = translate!("uptime-output-up-text");
|
||||
let uptime_message = get_formatted_uptime(None, OutputFormat::PrettyPrint)?;
|
||||
|
||||
println!("{localized_text} {uptime_message}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -205,6 +205,56 @@ pub fn get_uptime(boot_time: Option<time_t>) -> UResult<i64> {
|
||||
Err(UptimeError::SystemUptime)?
|
||||
}
|
||||
|
||||
/// The format used to display a FormattedUptime.
|
||||
pub enum OutputFormat {
|
||||
/// Typical `uptime` output (e.g. 2 days, 3:04).
|
||||
HumanReadable,
|
||||
|
||||
/// Pretty printed output (e.g. 2 days, 3 hours, 04 minutes).
|
||||
PrettyPrint,
|
||||
}
|
||||
|
||||
struct FormattedUptime {
|
||||
up_days: i64,
|
||||
up_hours: i64,
|
||||
up_mins: i64,
|
||||
}
|
||||
|
||||
impl FormattedUptime {
|
||||
fn new(up_secs: i64) -> Self {
|
||||
let up_days = up_secs / 86400;
|
||||
let up_hours = (up_secs - (up_days * 86400)) / 3600;
|
||||
let up_mins = (up_secs - (up_days * 86400) - (up_hours * 3600)) / 60;
|
||||
|
||||
Self {
|
||||
up_days,
|
||||
up_hours,
|
||||
up_mins,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_human_readable_uptime(&self) -> String {
|
||||
translate!(
|
||||
"uptime-format",
|
||||
"days" => self.up_days,
|
||||
"time" => format!("{:02}:{:02}", self.up_hours, self.up_mins))
|
||||
}
|
||||
|
||||
fn get_pretty_print_uptime(&self) -> String {
|
||||
let mut parts = Vec::new();
|
||||
if self.up_days > 0 {
|
||||
parts.push(translate!("uptime-format-pretty-day", "day" => self.up_days));
|
||||
}
|
||||
if self.up_hours > 0 {
|
||||
parts.push(translate!("uptime-format-pretty-hour", "hour" => self.up_hours));
|
||||
}
|
||||
if self.up_mins > 0 || parts.is_empty() {
|
||||
parts.push(translate!("uptime-format-pretty-min", "min" => self.up_mins));
|
||||
}
|
||||
parts.join(", ")
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the system uptime
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -227,26 +277,28 @@ pub fn get_uptime(_boot_time: Option<time_t>) -> UResult<i64> {
|
||||
/// # Arguments
|
||||
///
|
||||
/// boot_time: Option<time_t> - Manually specify the boot time, or None to try to get it from the system.
|
||||
/// output_format: OutputFormat - Selects the format of the output string.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns a UResult with the uptime in a human-readable format(e.g. "1 day, 3:45") if successful, otherwise an UptimeError.
|
||||
#[inline]
|
||||
pub fn get_formatted_uptime(boot_time: Option<time_t>) -> UResult<String> {
|
||||
pub fn get_formatted_uptime(
|
||||
boot_time: Option<time_t>,
|
||||
output_format: OutputFormat,
|
||||
) -> UResult<String> {
|
||||
let up_secs = get_uptime(boot_time)?;
|
||||
|
||||
if up_secs < 0 {
|
||||
Err(UptimeError::SystemUptime)?;
|
||||
}
|
||||
let up_days = up_secs / 86400;
|
||||
let up_hours = (up_secs - (up_days * 86400)) / 3600;
|
||||
let up_mins = (up_secs - (up_days * 86400) - (up_hours * 3600)) / 60;
|
||||
|
||||
Ok(translate!(
|
||||
"uptime-format",
|
||||
"days" => up_days,
|
||||
"time" => format!("{up_hours:02}:{up_mins:02}")
|
||||
))
|
||||
let formatted_uptime = FormattedUptime::new(up_secs);
|
||||
|
||||
match output_format {
|
||||
OutputFormat::HumanReadable => Ok(formatted_uptime.get_human_readable_uptime()),
|
||||
OutputFormat::PrettyPrint => Ok(formatted_uptime.get_pretty_print_uptime()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the number of users currently logged in
|
||||
|
||||
@@ -267,6 +267,15 @@ fn test_uptime_since() {
|
||||
new_ucmd!().arg("--since").succeeds().stdout_matches(&re);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uptime_pretty_print() {
|
||||
new_ucmd!()
|
||||
.arg("-p")
|
||||
.succeeds()
|
||||
.stdout_contains("up")
|
||||
.stdout_contains("minute");
|
||||
}
|
||||
|
||||
/// Test uptime reliability on macOS with sysctl kern.boottime fallback.
|
||||
/// This addresses intermittent failures from issue #3621 by ensuring
|
||||
/// the command consistently succeeds when utmpx data is unavailable.
|
||||
|
||||
Reference in New Issue
Block a user