在perl上显示bash脚本输出 - curses脚本

时间:2013-05-16 07:17:56

标签: perl bash output curses

我是Perl上的新手,并尝试使用Curses(Curses :: UI)在Perl中执行一个简单的脚本启动器

在Stackoverflow上,我找到了一个实时打印(在Perl中)Bash脚本输出的解决方案。

但我无法用我的Curses脚本执行此操作,将此输出写入TextEditor字段。

例如,Perl脚本:

#!/usr/bin/perl -w

use strict;
use Curses::UI;
use Curses::Widgets;
use IO::Select;

my $cui = new Curses::UI( -color_support => 1 );

[...]

my $process_tracking = $container_middle_right->add(
    "text", "TextEditor",
    -readonly       => 1,
    -text           =>  "",
);

sub launch_and_read()
{
    my $s = IO::Select->new();
    open my $fh, '-|', './test.sh';
    $s->add($fh);

    while (my @readers = $s->can_read()) {
        for my $fh (@readers) {
            if (eof $fh) {
                $s->remove($fh);
                next;
            }
            my $l = <$fh>;
            $process_tracking->text( $l );
            my $actual_text = $process_tracking->text() . "\n";
            my $new_text = $actual_text . $l;
            $process_tracking->text( $new_text );
            $process_tracking->cursor_to_end();
        }
    }
}

[...]

$cui->mainloop();

此脚本包含一个用于启动launch_and_read()的按钮。

test.sh:

#!/bin/bash
for i in $( seq 1 5 )
do
    sleep 1
    echo "from $$ : $( date )"
done

结果是我的应用程序在执行bash脚本时冻结,最后的输出在我的TextEditor字段末尾写入。

是否有解决方案可以实时显示Shell脚本中发生的情况,而不会阻止Perl脚本?

非常感谢,如果这个问题似乎很愚蠢,那就很抱歉:x

1 个答案:

答案 0 :(得分:0)

你不能阻止。 Curses的循环需要运行来处理事件。所以你必须民意调查。超时为零的select可用于轮询。

my $sel;

sub launch_child {
   $sel = IO::Select->new();
   open my $fh, '-|', './test.sh';
   $sel->add($fh);
}

sub read_from_child {
   if (my @readers = $sel->can_read(0)) {
      for my $fh (@readers) {
         my $rv = sysread($fh, my $buf, 64*1024);
         if (!$rv) {
            $sel->remove($fh);
            close($fh);
            next;
         }

         ... add contents of $buf to the ui here ...
      }
   }
}

launch_child();
$cui->set_timer(read_from_child => \&read_from_child, 1);
$cui->mainloop();

未测试。

请注意,我从readline<>)切换到sysread,因为前者会阻止,直到收到换行符。使用readreadline等阻止调用无法使用select。此外,使用readreadline等缓冲调用可能会导致select在实际存在时没有等待。切勿将readreadlineselect一起使用。