首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >解析并绘制从日志文件实时接收的数据。

解析并绘制从日志文件实时接收的数据。
EN

Stack Overflow用户
提问于 2013-10-14 10:05:27
回答 1查看 2K关注 0票数 1

我想要创建一个Perl (或Bash)脚本来动态创建和绘制数据。这意味着我希望从日志文件file.log中提取数据,理想情况下不要编写tmp-文件(如果只有tmp-文件才有可能,这也可以)和用Gnuplot绘图。随着日志文件的不断增长,我希望看到图中的其他信息。

类似的主题请参见this question

对于Perl,到目前为止,我拥有的是以下脚本:

代码语言:javascript
运行
复制
#!/usr/bin/perl
use strict;
use warnings;

my $path = "file.log";   
my @grepped;
my $switch = "off";

open(INFILE,"< $path") or die $! \n";
while (my $line = <INFILE>) {

       if ($line =~ m{^Time = (\d+)}){
               push(@grepped,"$1\t");
       };

       if ($line =~ m{^Errors: local = (\d+), global = (\d+)}){
               push(@grepped,"$1\t");
               push(@grepped,"$2\n");
               $switch = "refresh";
       };


if ($switch eq "refresh"){

open(GP, "| gnuplot -persist") or die: $! \n";
print GP << "GNU_EOF";

plot "@grepped" u 2:1
pause 1; refresh; reread;

GNU_EOF

close(GP);
}


}
close(INFILE)};

我的第一个问题是,Gnuplot的即时功能不起作用。当file.log被更改时,gnukett-图的刷新就无法工作了。我不知道-persist在这里是否正确,或者我是否必须使用replot选项而不是refresh。我试过了,但对我不起作用。

第二个问题是将数据读取到数组@grepped中,并在一个脚本中使用它来修改输入文件。另一个限制是(从代码中可以看到),如果在@grepped中写了一个完整的新行,gnuplot才应该刷新绘图。否则,由于数据分配错误,错误肯定会发生。

当我尝试一个简单的脚本时,比如:

代码语言:javascript
运行
复制
#!/usr/bin/gnuplot -persist
plot "data.dat" u 2:1
pause 1; replot; reread;

代码语言:javascript
运行
复制
#!/usr/bin/gnuplot
plot "data.dat" u 2:1
pause 1; refresh; reread;

如果我手动更改data.dat并保存它,就可以正常工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-14 12:04:24

这里有两种快速绘制数据的方法.

用粗图形循环

您必须一次又一次地调用plot,外部脚本对数据进行预处理。最小的gnuplot脚本filter.gp是:

代码语言:javascript
运行
复制
while (1) {
    plot '< ./myscript.pl' using 2:1
    pause 1
}

要阻止这种情况,请点击Ctrl+C

用于预处理的Perl脚本可能类似于以下myscript.pl

代码语言:javascript
运行
复制
#!/usr/bin/perl
use strict;
use warnings;

my $path = "file.log";   
my @grepped;
my $t = 0;
open(INFILE,"< $path") or die "$! \n";

while (my $line = <INFILE>) {
    if ($line =~ m{^Time = (\d+)}){
        $t = $1;
    };

    if ($line =~ m{^Errors: local = (\d+), global = (\d+)}){
        print "$t\t$1\t$2\n";
    };
};
close(INFILE);

只需使用gnuplot filter.gp运行它。

为了使它更可配置,可以更改脚本以使用通过命令行传递给gnuplot的变量:

代码语言:javascript
运行
复制
while (1) {
    plot '< ./myscript.pl -f '.path using 2:1
    pause 1
}

或为此使用reread

代码语言:javascript
运行
复制
plot '< ./myscript.pl -f '.path using 2:1
pause 1
reread

gnuplot -e "path='file.log';" filtermod.gp调用这个脚本。

这样可以工作,但是会一次又一次地过滤完整的文件。

从Perl到gnu图的管道

下面是一个Perl脚本,它基本上适合我,但它是我的第一个真正的Perl脚本,所以可能有一些不理想的部分。对此你可以发表评论。

代码语言:javascript
运行
复制
#!/usr/bin/perl
use strict;
use warnings;

my $path = "file.log";   
my @grepped;
my $switch = "off";

open(my $gp, "| gnuplot -persist") or die "$! \n";
$gp->autoflush(0);

use File::Tail;
my $file = File::Tail->new(name=>$path, maxinterval=>1, tail=>-1);

while (defined(my $line= $file->read)) {
    if ($line =~ m{^Time = (\d+)}){
        push(@grepped,"$1\t");
    };

    if ($line =~ m{^Errors: local = (\d+), global = (\d+)}){
        push(@grepped,"$1\t");
        push(@grepped,"$2\n");
        $switch = "refresh";
    };

    if ($switch eq "refresh") {
        print $gp <<"GNU_EOF";
plot '-' using 2:1
@grepped
e
GNU_EOF
        $gp->flush;
        $switch = "off"; 
    };
    Time::HiRes::sleep(0.1);
};

我发现这里很重要的是

  1. 遍历更改的文件。
  2. autoflushflush的排列。
  3. 允许gnuplot正确处理数据的sleep

它适用于一个非常小的测试数据文件。不知道它是否会对一个更大的,但应该帮助你更远一点。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19357830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档