为什么我不能重定向 awk 的输出?

为什么我不能重定向 awk 的输出?

我写了这一行代码来显示每 5 秒读取/写入的 MB。

#!/bin/bash
#iosum.sh
iostat -dmz 5 |\
    awk 'BEGIN{rx=wx=0}{if($0 == ""){printf"%.1f %.1f\n",rx,wx}else if($0~/^Device:/){rx=wx=0}else{rx+=$3;wx+=$4}}'

从命令行运行时,它运行完美

./iosum.sh
# wait
1.1 0.0
0.0 0.1
0.0 0.0
3.0 3.0
0.0 0.0
# ctrl-c

但是,当我尝试将输出放入文件时,我什么也没得到

./iosum.sh > out.txt
# wait
# ctrl-c
cat out.txt
# nothing!

是什么赋予了?

答案1

这是一个缓冲问题。Awk 的行为有所不同取决于它是否是交互式的。\n仅在后一种情况下刷新输出缓冲区,否则,正如您所体验到的,缓冲会一直发生,直到输出缓冲区已满或使用 fflush 命令明确刷新。

最终,如果您等待足够长的时间,输出文件中将会有一些内容。

否则,如果你kill 的话应该刷新输出iostat,而不是脚本本身。

或者,这里有一个简单的解决方法:

script -c iosum.sh out.txt

请注意,禁用缓冲(使用script或显式fflush)会影响性能,因此如果您不需要监视文件内容(例如,两分钟的捕获期),则终止iostat进程(pkill -f "iostat -dmz 5")或将其设置为在给定时间段后终止是更好的方法:

iostat -dmz 5 120 |\
    awk 'BEGIN{rx=wx=0}{if($0 == ""){printf"%.1f %.1f\n",rx,wx}else if($0~/^Device:/){rx=wx=0}else{rx+=$3;wx+=$4}}'

答案2

Awk 缓冲所有输出,只有当它完成读取输入或缓冲区已满时才将其写出。fflush(stdout)在 awk 脚本中使用(请参阅 awk 手册页)确保在打印每行后将输出正确刷新到磁盘。如下所示:

iostat -dmz 5 |\
       awk 'BEGIN{rx=wx=0}{if($0 == ""){printf"%.1f %.1f\n",rx,wx;fflush(stdout)}else if($0~/^Device:/){rx=wx=0}else{rx+=$3;wx+=$4}}' > x

相关内容