在Perl中正确捕获shell脚本输出

时间:2014-10-14 07:26:29

标签: perl shell output

首先,我知道这个问题被多次询问过,但是这里没有找到解决方案似乎对我有所帮助:/

我尝试在Perl中创建一个可以启动一些shell脚本的接口。

我的想法是获取shell脚本输出(stdout和stderr)并在我主窗口的另一帧上实时显示。

问题:

输出没有保存在变量中,它立即显示在屏幕中间,我不明白这种行为..

以下是结果的简短截图:

-deleted -

目标是在“进度”框架中显示输出;我尝试了很多Perl方法来实现这个功能,但每次都失败了......

以下是我尝试过的一些例子:

sub launch_child(@)
{
    my $pid = open(KID, '-|');
    die "fork: $!" unless defined($pid);
    if($pid) {
        my $output;
        while (<KID>) {
            $process_tracking->text($process_tracking->text() .  "$_");
        }
        close(KID);
    } else {
        exec @_;
    }
}

sub launch_child()
{
    my $sel = IO::Select->new();
    open my $fh, '-|', './shell_script.sh';
    while (<$fh>) {
        $process_tracking->text($process_tracking->text() .  "$_" );
    }
    close $fh;
    $sel->add($fh);
    push( @selects , $sel );
}

感谢所有可以帮助我实现这一目标的Perl专家;)

编辑:

我找到了一种方法(感谢choroba的“stderr”线索):

my @selects = ();

sub launch_child()
{
    my $sel = IO::Select->new();
    open my $fh, '-|', './shell_script.sh 2>&1';
    $sel->add($fh);
    push( @selects , $sel );
}
sub read_from_child()
{
    if (scalar @selects > 0) {
        for my $sel (@selects) {
            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;
                    }
                    $process_tracking->text($process_tracking->text().$buf);
                    $process_tracking->cursor_to_end();
                }
            }
        }
    }
}

while (1) {
    $cui->{-read_timeout} = 0;
    $cui->do_one_event();
    read_from_child();
    sleep 0.1;
}

新结果的屏幕截图:

-deleted -

现在,我问为什么不评估shell脚本中的颜色:echo -ne [...]

1 个答案:

答案 0 :(得分:1)

您正在正确读取过程的STDOUT,但STDERR可以直接自由地进入屏幕。有关详细信息,请参阅perlipc