我写了这一行代码来显示每 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