暗无天日

=============>DarkSun的个人博客

为ping命令增加时间信息的正确方法

不知道为什么,在网上搜索为 ping 命令增加时间信息方法时,给出来得解决方案都是将 ping 命令的结果传递给一个循环,然后在循环内生成时间。

这个循环可能是一个流式处理命令,比如 awk:

ping www.baidu.com -c 5 | awk '{ print strftime("%Y-%m-%d %H:%M:%S",systime())"\t"$0 }'
2021-04-26 11:26:24     PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data.
2021-04-26 11:26:24     64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=52 time=12.1 ms
2021-04-26 11:26:24     64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=52 time=9.51 ms
2021-04-26 11:26:25     64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=3 ttl=52 time=18.4 ms
2021-04-26 11:26:26     64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=4 ttl=52 time=15.4 ms
2021-04-26 11:26:27     64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=5 ttl=52 time=9.81 ms
2021-04-26 11:26:27     
2021-04-26 11:26:27     --- www.a.shifen.com ping statistics ---
2021-04-26 11:26:27     5 packets transmitted, 5 received, 0% packet loss, time 10077ms
2021-04-26 11:26:27     rtt min/avg/max/mdev = 9.519/13.089/18.481/3.432 ms

也可能是一个 while 循环语句:

ping www.baidu.com -c 5 |while read result
do
    echo "$(date) ${result}"
done
2021年 04月 26日 星期一 11:25:09 CST PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data.
2021年 04月 26日 星期一 11:25:09 CST 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=52 time=8.73 ms
2021年 04月 26日 星期一 11:25:09 CST 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=52 time=16.4 ms
2021年 04月 26日 星期一 11:25:10 CST 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=3 ttl=52 time=9.98 ms
2021年 04月 26日 星期一 11:25:11 CST 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=4 ttl=52 time=10.8 ms
2021年 04月 26日 星期一 11:25:12 CST 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=5 ttl=52 time=17.3 ms
2021年 04月 26日 星期一 11:25:12 CST 
2021年 04月 26日 星期一 11:25:12 CST --- www.a.shifen.com ping statistics ---
2021年 04月 26日 星期一 11:25:12 CST 5 packets transmitted, 5 received, 0% packet loss, time 7043ms
2021年 04月 26日 星期一 11:25:12 CST rtt min/avg/max/mdev = 8.731/12.684/17.392/3.548 ms

但是这有个问题,那就是时间戳不是由 ping 命令生成的,而是在循环体内生成的。这就导致若我们在时间戳生成之前用 sedawk 之类的命令对 ping 结果加工后,由于它们的缓存机制会使得输出到循环的时间比实际 ping 命令产生结果的时间产生较大差别。

例如下面命令的输出中,生成的时间是同一秒,这明显是不对的。

ping www.baidu.com -c 5|awk '1' | awk '{ print strftime("%Y-%m-%d %H:%M:%S",systime())"\t"$0 }'
2021-04-26 11:27:01     PING www.a.shifen.com (14.215.177.39) 56(84) bytes of data.
2021-04-26 11:27:01     64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=1 ttl=52 time=13.2 ms
2021-04-26 11:27:01     64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=2 ttl=52 time=8.32 ms
2021-04-26 11:27:01     64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=3 ttl=52 time=18.1 ms
2021-04-26 11:27:01     64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=4 ttl=52 time=8.61 ms
2021-04-26 11:27:01     64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=5 ttl=52 time=9.09 ms
2021-04-26 11:27:01     
2021-04-26 11:27:01     --- www.a.shifen.com ping statistics ---
2021-04-26 11:27:01     5 packets transmitted, 5 received, 0% packet loss, time 4052ms
2021-04-26 11:27:01     rtt min/avg/max/mdev = 8.322/11.492/18.191/3.794 ms

事实上,通过查看 ping 命令的 manual, 我们可以发现 ping 命令的 -D 选项本身就会为每一行输出生成时间戳:

-D     Print timestamp (unix time + microseconds as in gettimeofday) before each line.
ping -c 5 www.baidu.com -D
PING www.a.shifen.com (14.215.177.39) 56(84) bytes of data.
[1619407749.478198] 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=1 ttl=52 time=8.86 ms
[1619407749.492436] 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=2 ttl=52 time=13.8 ms
[1619407750.493666] 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=3 ttl=52 time=13.4 ms
[1619407751.492797] 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=4 ttl=52 time=10.5 ms
[1619407752.501662] 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=5 ttl=52 time=17.1 ms

--- www.a.shifen.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4042ms
rtt min/avg/max/mdev = 8.861/12.776/17.120/2.861 ms

唯一的问题就是这个时间戳采取的是是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不方便理解,但是没关系,我们可以用 date 进行一下转换:

ping -c 5 www.baidu.com -D |awk '1' |while read result
do
    if [[ "${result}" =~ "[" ]] # 以 [ 开头的行带时间戳
    then
       read timestamp rest < <(echo ${result}|tr -d '[]')
       echo $(date -d @${timestamp}) "${rest}"
       else
           echo "${result}"
    fi
done
PING www.a.shifen.com (14.215.177.39) 56(84) bytes of data.
2021年 04月 26日 星期一 11:41:25 CST 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=1 ttl=52 time=8.97 ms
2021年 04月 26日 星期一 11:41:25 CST 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=2 ttl=52 time=7.89 ms
2021年 04月 26日 星期一 11:41:26 CST 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=3 ttl=52 time=27.3 ms
2021年 04月 26日 星期一 11:41:27 CST 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=4 ttl=52 time=20.6 ms
2021年 04月 26日 星期一 11:41:28 CST 64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=5 ttl=52 time=22.2 ms

--- www.a.shifen.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4069ms
rtt min/avg/max/mdev = 7.897/17.425/27.343/7.671 ms