3

我有一个程序将持续运行,将输出写入标准输出,我想不断地从中获取最后一组输出并将其写入文件。每次出现一组新的输出时,我都想覆盖同一个文件。

一个示例是以下命令:

iostat -xkd 5

每 5 秒打印一些输出,每个输出后都有一个空行。我希望将最后一个“集合”写入文件,我认为这应该可以通过一些简单的方法来实现。

到目前为止,我已经尝试过使用 xargs,我只能用一行来做到这一点,而不是一组由某些东西分隔的行。

我认为使用 awk 可能是可行的,但我不知道如何让它在数据传输过程中缓冲数据,以便它可以使用系统将其写出,或者让它关闭并重新打开同一个输出文件。

编辑:为了澄清,这是一个将连续运行的命令。我不想启动一个新命令并阅读它的输出。

解决方案

我改编了@Bittrance 的答案以获得以下信息:

iostat -xkd 5 | (while read r; do
        if [ -z "$r" ]; then
                mv -f /tmp/foo.out.tmp /tmp/foo.out
        else
                echo "$r" >> /tmp/foo.out.tmp
        fi
done)

这基本上是相同的,除了检测“节”的结尾并写入临时文件以便每当外部进程尝试读取输出文件时它就会完成。

4

3 回答 3

1

部分答案:

./your_command | (while read r ; do 
    if ... ; then
        rm -f foo.out
    fi
    echo $r >> foo.out
done)

如果有一个条件(...),您知道您正在接收“集合”的第一行,这将起作用。

于 2012-07-12T20:11:01.110 回答
0

编辑在回复评论时,我测试了这个 perl 解决方案的工作:

#!/usr/bin/perl
use strict;
use warnings;

$|=1;

open(STDOUT, '>', '/tmp/iostat.running') or die $!;

while(<>)
{
    seek (STDOUT, 0, 0) if (m/^$/gio);
    print
}

所以现在你可以

iostat -xkd 5 | myscript.pl&

并观看快照:

watch -n10 cat /tmp/iostat.running

如果您想确保最后有足够的空间被覆盖(因为每次输出长度可能略有不同),您可以在最后打印一些填充,例如:

    print "***"x40 and seek (STDOUT, 0, 0) if (m/^$/gio);

(剪掉旧的答案文本,因为它显然让人们感到困惑)

于 2012-07-12T20:26:33.023 回答
0

为什么不:

while :; do
  iostat -xkd > FILE
  sleep 5
done

如果您使用awk以下设置将每个输出写入iostat编号文件:

iostat -xkd 5 | awk -v RS=$'\n'$'\n' '{ print >NR; close(NR) }'

注意:第一条记录是iostat输出的表头。

于 2012-07-12T20:13:45.397 回答