0

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

在 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

4

1 回答 1

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因为前一个阻塞,直到收到换行符。read使用像或这样的阻塞调用readline违背了使用的意义selectread此外,使用像or这样的缓冲调用readline可能会导致select在实际等待时什么都不在等待。永远不要使用readand readlineselect

于 2013-05-16T07:40:05.757 回答