不知道为什么,在网上搜索为 ping 命令增加时间信息方法时,给出来得解决方案都是将 ping 命令的结果传递给一个循环,然后在循环内生成时间。
这个循环可能是一个流式处理命令,比如 awk:
ping www.baidu.com -c 5 | awk '{ print strftime("%Y-%m-%d %H:%M:%S",systime())"\t"$0 }'
也可能是一个 while 循环语句:
ping www.baidu.com -c 5 |while read result
do
echo "$(date) ${result}"
done
但是这有个问题,那就是时间戳不是由 ping
命令生成的,而是在循环体内生成的。这就导致若我们在时间戳生成之前用 sed
和 awk
之类的命令对 ping
结果加工后,由于它们的缓存机制会使得输出到循环的时间比实际 ping 命令产生结果的时间产生较大差别。
例如下面命令的输出中,生成的时间是同一秒,这明显是不对的。
ping www.baidu.com -c 5|awk '1' | awk '{ print strftime("%Y-%m-%d %H:%M:%S",systime())"\t"$0 }'
事实上,通过查看 ping
命令的 manual, 我们可以发现 ping 命令的 -D
选项本身就会为每一行输出生成时间戳:
-D Print timestamp (unix time + microseconds as in gettimeofday) before each line.
ping -c 5 www.baidu.com -D
唯一的问题就是这个时间戳采取的是是从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