【问题标题】:Bash format uptime to show days, hours, minutesBash 格式正常运行时间以显示天、小时、分钟
【发布时间】:2015-02-05 20:27:42
【问题描述】:

我在 bash 中使用 uptime 来获取机器的当前运行时间。我需要获取时间并显示格式,例如 2 天 12 小时 23 分钟。

【问题讨论】:

标签: linux bash uptime


【解决方案1】:

我的uptime 产生如下输出:

$ uptime
 12:49:10 up 25 days, 21:30, 28 users,  load average: 0.50, 0.66, 0.52

要将其转换为您的格式:

$ uptime | awk -F'( |,|:)+' '{print $6,$7",",$8,"hours,",$9,"minutes."}'
25 days, 21 hours, 34 minutes.

工作原理

  • -F'( |,|:)+'

    awk 将其输入划分为多个字段。这告诉 awk 使用空格、逗号或冒号中的一个或多个的任意组合作为字段分隔符。

  • print $6,$7",",$8,"hours,",$9,"minutes."

    这告诉 awk 打印第六个字段和第七个字段(用空格分隔),然后是逗号、第 8 个字段、字符串hours,、第九个字段,最后是字符串minutes.

使用 sed 处理正常运行时间较短的计算机

从重新启动开始,我的 uptime 产生如下输出:

 03:14:20 up 1 min,  2 users,  load average: 2.28, 1.29, 0.50
 04:12:29 up 59 min,  5 users,  load average: 0.06, 0.08, 0.48
 05:14:09 up  2:01,  5 users,  load average: 0.13, 0.10, 0.45
 03:13:19 up 1 day, 0 min,  8 users,  load average: 0.01, 0.04, 0.05
 04:13:19 up 1 day,  1:00,  8 users,  load average: 0.02, 0.05, 0.21
 12:49:10 up 25 days, 21:30, 28 users,  load average: 0.50, 0.66, 0.52

以下sed 命令处理这些格式:

uptime | sed -E 's/^[^,]*up *//; s/, *[[:digit:]]* users.*//; s/min/minutes/; s/([[:digit:]]+):0?([[:digit:]]+)/\1 hours, \2 minutes/' 

根据上述时间,这会产生:

1 minutes
59 minutes
2 hours, 1 minutes
1 day, 0 minutes
1 day,  1 hours, 0 minutes
25 days, 21 hours, 30 minutes

工作原理

  • -E 打开扩展的正则表达式语法。 (在较旧的 GNU seds 上,使用 -r 代替 -E

  • s/^[^,]*up *//

    此替换命令会删除直到 up 的所有文本。

  • s/, *[[:digit:]]* users.*//

    这个替代命令会删除用户计数和它后面的所有文本。

  • s/min/minutes/

    这会将min 替换为minutes

  • s/([[:digit:]]+):0?([[:digit:]]+)/\1 hours, \2 minutes/'

    如果该行包含 hh:mm 格式的时间,这会将小时与分钟分开,并将其替换为 hh hours, mm minutes

使用 awk 处理正常运行时间较短的计算机

uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'

在与上述相同的测试用例中,这会产生:

0 days, 0 hours, 1 minutes.
0 days, 0 hours, 59 minutes.
0 days, 2 hours, 1 minutes.
1 days, 0 hours, 0 minutes.
1 days, 1 hours, 0 minutes.
25 days, 21 hours, 30 minutes.

对于那些喜欢分散在多行上的 awk 代码的人:

uptime | awk -F'( |,|:)+' '{
    d=h=m=0;
    if ($7=="min")
        m=$6;
    else {
        if ($7~/^day/) { d=$6; h=$8; m=$9}
        else {h=$6;m=$7}
        }
    }
    {
        print d+0,"days,",h+0,"hours,",m+0,"minutes."
    }'

【讨论】:

  • 感谢 awk 解决方案。将具有多个正常运行时间的文件传输到其中时的一个小改进,我需要重置变量:cat filewithuptimes.log | awk -F'( |,|:)+' 'd=0; h=0; m=0; {if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'
  • @mrvulcan 很好的观察!我刚刚更新了初始化这些变量的答案,以便处理多个输入行的情况。谢谢。
【解决方案2】:

只是为了完整性...是关于什么的:

$ uptime -p
up 2 weeks, 3 days, 14 hours, 27 minutes

【讨论】:

  • 应该是一个可接受的答案。在 ubuntu 上适用于我,但不适用于 OSX。
  • 这对 ubuntu 很好,但在 redhat 上不起作用。因为@John 的答案很棒。
【解决方案3】:

解决方案:为了以秒为单位获得 linux 的正常运行时间,请转到 bash 并输入 cat /proc/uptime。解析第一个数字并根据您的要求进行转换。

来自 RedHat documentation:

此文件包含系统自上次重新启动后运行了多长时间的详细信息/proc/uptime 的输出非常小:

350735.47 234388.90

First 数字是系统已运行的总秒数 起来。

Second数字是机器花费了多少时间 闲置,在 秒。

【讨论】:

  • 请记住,这是特定于 Linux 的——它不适用于其他 POSIX 操作系统(除非它们旨在模仿 Linux)
  • 您心目中的 POSIX 而非 Linux 操作系统是什么?
  • macOS 就是这样一种操作系统。 @R.W.普拉多
【解决方案4】:

我为支持uptime -p 的系统(如较新的 linux)和不支持的系统(如 Mac OS X)制作了一个通用 shell 脚本。

#!/bin/sh

uptime -p >/dev/null 2>&1

if [ "$?" -eq 0 ]; then
  # Supports most Linux distro
  # when the machine is up for less than '0' minutes then
  # 'uptime -p' returns ONLY 'up', so we need to set a default value
  UP_SET_OR_EMPTY=$(uptime -p | awk -F 'up ' '{print $2}')
  UP=${UP_SET_OR_EMPTY:-'less than a minute'}
else
  # Supports Mac OS X, Debian 7, etc
  UP=$(uptime | sed -E 's/^[^,]*up *//; s/mins/minutes/; s/hrs?/hours/;
  s/([[:digit:]]+):0?([[:digit:]]+)/\1 hours, \2 minutes/;
  s/^1 hours/1 hour/; s/ 1 hours/ 1 hour/;
  s/min,/minutes,/; s/ 0 minutes,/ less than a minute,/; s/ 1 minutes/ 1 minute/;
  s/  / /; s/, *[[:digit:]]* users?.*//')
fi

echo "up $UP"

Gist

使用我自己的自定义引用 John1024 答案。

【讨论】:

  • 非常适合我的需要,+1 用于正确的奇异值格式 :)
【解决方案5】:

为此:

  • 0 天 0 小时 1 分钟。
  • 0 天 0 小时 59 分钟。
  • 0 天 2 小时 1 分钟。
  • 1 天 0 小时 0 分钟。
  • 1 天 1 小时 0 分钟。
  • 25 天 21 小时 30 分钟

更简单的是:
uptime -p | cut -d " " -f2-

【讨论】:

  • 这不会打印“0 天”之类的内容,至少在 procps-ng 3.3.16 的正常运行时间中不会。
【解决方案6】:

为了多样化,这里以 sed 为例:

我的原始输出:

$ uptime
15:44:56 up 3 days, 22:58,  7 users,  load average: 0.48, 0.40, 0.31

转换后的输出:

$uptime|sed 's/.*\([0-9]\+ days\), \([0-9]\+\):\([0-9]\+\).*/\1, \2 hours, \3 minutes./'
3 days, 22 hours, 58 minutes.

【讨论】:

    【解决方案7】:

    这个答案对于 OS X 中的uptime 非常具体,但会考虑任何输出情况。

    #!/bin/bash
    
    INFO=`uptime`
    echo $INFO | awk -F'[ ,:\t\n]+' '{
            msg = "↑ "
            if ($5 == "day" || $5 == "days") {      # up for a day or more
                msg = msg $4 " " $5 ", "
    
                n = $6
                o = $7
            } else {
                n = $4
                o = $5
            }
    
            if (int(o) == 0) {                      # words evaluate to zero
                msg = msg int(n)" "o
            } else {                                # hh:mm format
                msg = msg int(n)" hr"
                if (n > 1) { msg = msg "s" }
    
                msg = msg ", " int(o) " min"
                if (o > 1) { msg = msg "s" }
            }
    
            print "[", msg, "]"
        }'
    

    一些可能的输出示例:

    22:49 up 24 secs, 2 users, load averages: 8.37 2.09 0.76
    [ ↑ 24 secs ]
    
    22:50 up 1 min, 2 users, load averages: 5.59 2.39 0.95
    [ ↑ 1 min ]
    
    23:39 up 51 mins, 3 users, load averages: 2.18 1.94 1.74
    [ ↑ 51 mins ]
    
    23:54 up 1:06, 3 users, load averages: 3.67 2.57 2.07
    [ ↑ 1 hr, 6 mins ]
    
    16:20 up 120 days, 10:46, 3 users, load averages: 1.21 2.88 0.80
    [ ↑ 120 days, 10 hrs, 46 mins ]
    

    【讨论】:

      【解决方案8】:
      uptime_minutes() {
        set `uptime -p`
        local minutes=0
      
        shift
        while [ -n "$1" ]; do
          case $2 in
            day*)
              ((minutes+=$1*1440))
              ;;
            hour*)
              ((minutes+=$1*60))
              ;;
            minute*)
              ((minutes+=$1))
              ;;
          esac
         shift
         shift
        done
      
        echo $minutes
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-16
        • 2020-09-08
        • 2011-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-22
        相关资源
        最近更新 更多