【问题标题】:Retrieving stdout and stderr while using tkx::open to run external commands在使用 tkx::open 运行外部命令时检索标准输出和标准错误
【发布时间】:2015-01-04 06:20:04
【问题描述】:

我已经设法在 Perl(Tkx 模块)中从 Tk GUI 运行外部命令没有阻塞 GUI

但是,我很难从 stderr 和 stdout 检索消息:对于大多数命令,变量 $stdout$stderr 中没有存储任何内容。

我的代码中缺少什么?

谢谢

use Tkx;
use strict;
use Data::Dumper;

my ($stdout,$stderr);

my $mw = Tkx::widget->new(".");
my $button=$mw->new_ttk__button(-text => "Run", -command => [\&run_command, "systeminfo"]);
$button->g_grid(-column => 0, -row => 0);
my $text = $mw->new_tk__text(-width => 32, -height => 16);
$text->insert("end", "Test\n");
$text->g_grid(-column => 0, -row => 1);

Tkx::MainLoop();
print "STDOUT: $stdout\n\n","-"x24,"\nSTDERR: $stderr\n";


sub run_command {
    my $cmd = shift;
    my $fh = Tkx::open("| $cmd", 'r') or die "$!";
    Tkx::fconfigure($fh, -blocking => 0);
    $stdout.=Tkx::read($fh);
    eval { Tkx::close($fh); };
    $stderr.=$@ if ($@);

}

【问题讨论】:

    标签: perl tkx


    【解决方案1】:

    在 Linux 上,我可以使用 Capture::Tiny 来获取外部命令的输出:

    use strict;
    use warnings;
    
    use Capture::Tiny ();
    use Tkx;
    
    my ($stdout,$stderr);
    
    my $mw = Tkx::widget->new(".");
    my $button=$mw->new_ttk__button(-text => "Run", -command => [\&run_command, "echo aaa; eeee"]);
    $button->g_grid(-column => 0, -row => 0);
    my $text = $mw->new_tk__text(-width => 32, -height => 16);
    $text->insert("end", "Test\n");
    $text->g_grid(-column => 0, -row => 1);
    
    Tkx::MainLoop();
    
    sub run_command {
        my $cmd = shift;
        my ($stdout, $stderr, $exit) = Capture::Tiny::capture {
            system($cmd);
        };
        print "STDOUT: '$stdout'\n";
        print "STDERR: '$stderr'\n";
        print "Exit code: '$exit'\n";
    }
    

    输出:

    STDOUT: 'aaa
    '
    STDERR: 'sh: 1: eeee: not found
    '
    Exit code: '32512'
    

    编辑

    为避免阻塞 GUI,请开发一个小的包装脚本,例如:

    $ cat wrapperl.pl
    use strict;
    use warnings;
    use Capture::Tiny;
    
    my $cmd = shift;
    
    my ($stdout, $stderr, $exit) = Capture::Tiny::capture {
        system($cmd);
    };
    print "Child is waiting..\n";
    sleep 2;
    print "STDOUT: '$stdout'\n";
    print "STDERR: '$stderr'\n";
    print "Exit code: '$exit'\n";
    

    然后使用:

    sub run_command {
        my $cmd = shift;
        my $fh;
        print "Master: calling command..\n";
        system ("wrapper.pl \"$cmd\" &");
        print "Master: returning to Tkx::Mainloop..\n";
    }
    

    输出:

    Master: calling command..
    Master: returning to Tkx::Mainloop..
    Child is waiting..
    STDOUT: 'aaa
    '
    STDERR: 'sh: 1: eeee: not found
    '
    Exit code: '32512'
    

    【讨论】:

    • 谢谢,这是一个有趣的建议。您是否有不阻塞 Tk GUI 的替代方案或方法来实现它?谢谢
    猜你喜欢
    • 2020-05-26
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    相关资源
    最近更新 更多