如何将 kubernetes 风格的时间转换为秒,以便我可以进行一些比较

如何将 kubernetes 风格的时间转换为秒,以便我可以进行一些比较

kubectl get pods -o wide

输出看起来类似于

some-pod-name-with-numbers-123             1/1     Running   0          6d4h      192.168.0.23   node-name-abcdeft-host.domain   <none>           <none>
some-pod-name-with-numbers-1234            1/1     Running   0          4h38m      192.168.0.24   node-name-abcdeft-host.domain   <none>           <none>
some-pod-name-with-numbers-1235            1/1     Running   0          2m38s      192.168.0.25   node-name-abcdeft-host.domain   <none>           <none>

我得到 Pod 的经过时间,格式如下:4d3h15m3s(看起来最多是两个连续的单位,天和小时,小时分钟,分钟和秒,但我不能保证这一点。

我需要检查 pod 的存在时间是否超过某个阈值 X。

我试图找到某种方法通过 kubectl 将该字段提取为秒,但没有运气。我在互联网上搜索了一种预装解决方案,但找不到。

我想我可以使用 awk 将字符串转换为数字秒,这样我就可以比较它是否 > $X,这个值是可配置的。

答案1

您不需要仅仅为了获取 kubernetes 运行时间(以秒为单位)而派生外部进程。下面的 GNU awk 代码有一个用户定义的函数fx(),该函数将执行该转换,从那里您可以将其用于比较目的。

kubectl get pods -o wide |
awk '
BEGIN {
    a["d"] = 24*(\
    a["h"] = 60*(\
    a["m"] = 60*(\
    a["s"] = 1)));
  }
  {
    print fx($5); # kubernetes time elapsed in seconds 
  }
  function fx(ktym,    f,u,n,t,i) {
    n = split(ktym, f, /[dhms]/, u)
    t = 0
    for (i=1; i<n; i++) {
      t += f[i] * a[u[i]] 
    }
    return t
  }
'

如果你想使用 bash 中的用户定义函数,那么我们可以执行以下操作。我们有一个函数 fx(),它需要一个参数,即以 kubernetes 格式表示的经过时间,它将以秒为单位输出时间。

fx() {
echo "$1" |
sed -Ee '
  s/[1-9][0-9]*[dhms]/&+ /g
  :a;s/[+]([^+].*)/\1+/;ta
  s/.$//
  :loop
    s/d/ 24h*/
    s/h/ 60m*/
    s/m/ 60s*/
    s/s//
  t loop
  s/.*/echo "&" | dc -e "?p"/e
'
}

我们正在为名为的 Linux 实用程序动态生成代码直流电或桌面计算器RPN(逆波兰表示法)。

答案2

如果有人像我一样在寻找 python 函数,这里是:

def kubctle_dur_to_secs(kubectl_time:str) -> int:
    total_time = 0
    for t_char, sec_in_t in zip( ('d', 'h', 'm', 's'), (86400, 3600, 60, 1) ):
        if t_char in kubectl_time:
            t_index = kubectl_time.find(t_char)
            total_time += int(kubectl_time[:t_index])*sec_in_t
            kubectl_time = kubectl_time[t_index+1:]
    return total_time

答案3

花了一些时间,发现最快的方法是用 sed 替换来标记时间。

sed -e 's/\([smhd]\)/\1 /g' | awk '{ b=0; for(i=1; i<=NF; ++i) { s=substr($i,1,length($i)-1); u=substr($i,length($i)); if (u=="s") b+=s; else if (u=="m") b+=s*60; else if (u=="h") b+=s*60*60; else if (u=="d") b+=s*60*60*24; else u=""; } if (b>1) printf "%d", b}'

到目前为止,我只观察到该领域使用了 d、h、m、s 单位,即使对于超过 100 天的 pod 也是如此。

sed 命令基本上用空格分隔每个单元。
然后 awk 循环遍历字段并将字符串拆分为单位 (u) 和数字字符串 (s)。
链接的 if-elseif-else 语句只是根据单位将值转换为秒,并将其添加到保留的总时间(以秒为单位)中。

我已将此命令放在脚本“kube_elapsed_to_seconds”中,并计划在外部使用另一个 awk 和系统命令在此字段上运行此脚本。

kubectl get pods -o wide | awk '{ system("echo " $5 " | kube_elapased_to_seconds"); print $0 }'

我愿意接受有关如何使此命令更易于阅读或与其他非时间相关字段(例如可能存在的 podname 和状态)更好地交互的建议。

答案4

对于理解这些的命令4d3h15m3s,请参阅 dateutils 的dadd

$ TZ=UTC0 dateutils.dadd -f%s 1970-01-01T00:00:00 4d3h15m3s
357303

这里将该持续时间添加到 Unix 纪元时间的开头,并将结果输出为 Unix 纪元时间(在与 UTC 偏移量为 0 的时区中)。

相关内容