Получение stdout и stderr при использовании tkx::open для запуска внешних команд
Мне удалось запустить внешние команды из Tk GUI в Perl (модуль Tkx), не блокируя 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 ($@);
}
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'
редактировать
Чтобы избежать блокировки графического интерфейса, разработайте небольшой скрипт-обертку, например:
$ 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'