【问题标题】:Using sed piped with w command show user with the largest idle time使用带有 w 命令的 sed 管道显示空闲时间最长的用户
【发布时间】:2017-02-12 09:44:10
【问题描述】:

w 命令产生如下内容:

01:19:02 up 53 days, 10:44, 15 users,  load average: 0.00, 0.02, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
higrheht pts/5    c-13-76-207-161. 23:21    2:05   0.07s  0.07s -bash
sgergrgr pts/6    c-97-164-31-14.h 00:54    2.00s  0.04s  0.04s -bash
jwegrgrng pts/14   c-23-71-12-251.h 22:48    8:03   0.07s  0.06s vim s2
hiqrefan pts/18   c-13-31-206-169. 23:19    0.00s  0.01s  0.01s -bash
hqeffran pts/19   c-19-71-206-169. 23:19    1:58m  0.02s  0.02s -bash
aqrgri   pts/20   c-84-6-212-27.hs 23:21    0.00s  0.19s  0.17s -bash

我必须得到一个 sed 脚本来打印空闲时间最长的用户。但问题是 w 以 3 种不同格式显示空闲时间:1) 以秒为单位:以 's' 结尾,2) mm:ss(不以 'm' 或 's' 结尾),以及 3) hh: mm(以“m”结尾)。所以我需要以某种方式制作一个可以使用它的 sed 脚本,但我似乎无法做到。

我的尝试: 有 2 个变量将首先设置,以找出最高空闲时间是形式 1 还是 2 或 3。那部分已经完成。然后基于此,我将提取该空闲字段中的文本并将其与变量进行比较,如果时间较长则替换。但它最后有一个字母!所以它不能作为一个数字来比较。它是一个字符串。这就是问题所在。

BEGIN{view1=0
view3=0
userid=""
idlemax=""}

NR>2{
        if($5 ~ /s$/)
        {
            view2=1
        }

        if($5 ~ /m$/)
        {
          view3= 1
        }

}

【问题讨论】:

    标签: linux bash unix awk gawk


    【解决方案1】:

    空闲时间并不比用户登录的 TTY 设备的最后一次访问时间更复杂。因此,一种简单的方法是获取所有登录的 TTY 用户的姓名并stat他们:

    who -s | awk '{ print $2 }' | (cd /dev && xargs stat -c '%n %U %X')
    

    在某些系统上,这会为登录会话(例如不在真实 tty 上的 X11 会话)发出错误。

    如果您想要年龄而不是绝对时间,请对其进行后处理以从当前时间中减去它:

    who -s | awk '{ print $2 }' | (cd /dev && xargs stat -c '%n %U %X') |
        awk '{ print $1"\t"$2"\t"'"$(date +%s)"'-$3 }'
    

    或者使用perl-A操作符:

    who -s | perl -lane 'print "$F[1]\t$F[0]\t" . 86400 * -A "/dev/$F[1]"'
    

    来自here

    【讨论】:

      【解决方案2】:

      你可以用 bash 来代替 sed:

          #!/bin/bash
      
          decode_seconds()
          {
              echo "${1%%.*}"
          }
      
          decode_hrs()
          {
            echo $(( $( decode_pair "${1}") * 60 ))
          }
      
          decode_pair()
          {
            local value="${1}"
            local right="${value##*:}"
            local left="${value%%:*}"
            echo $(( (left * 60 ) + right ))
          }
      
          decode_value()
          {
            local value="${1}"
            local units="${2}"
      
            case "${units}" in 
              seconds) decode_seconds "${value}" ;;
              hours)   decode_hrs "${value}" ;;
              *)       decode_pair "${value}" ;;
            esac
          }
      
          process_data()
          {
            while read user value units extra ; do 
              echo $(decode_value "${value}" "${units}") "${user}"
            done
          }
      
          w | awk '{print $1,$5}' \
            | sed \
              -e 's/s$/ seconds/' \
              -e 's/m$/ hours/' \
            | process_data \
            | sort -rn
      

      【讨论】:

      • 你只考虑分钟和秒,输出可以是天、周、月甚至年!
      • 我相信他可以在获得具有该格式的示例时添加这一点,但我没有可以使用几天或几年的示例。我发布的内容很容易让任何人理解和扩展。
      猜你喜欢
      • 2017-09-04
      • 1970-01-01
      • 2022-06-21
      • 2012-10-31
      • 2016-11-11
      • 2013-08-07
      • 2022-11-04
      • 2021-06-28
      相关资源
      最近更新 更多