我正在嘗試使用 Capture::Tiny 將 STDOUT 捕獲到檔案中。
為了給你更大的圖景,我的最終目標是:
- 在命令列上運行 Blender 行程
- 將日志捕獲到檔案句柄
- 觀察檔案句柄“增長”
- 將檔案句柄的內容通過管道傳輸到 websocket,供用戶通過網頁查看進度
我的計劃是使用 Capture::Tiny,以及此執行緒中提供的示例。
但是我被困在第 1 步:我可以像這樣捕獲 STDOUT 和 STDERR:
use IO::File;
use Capture::Tiny qw/capture/;
$\ = "\n"; $, = "\t";
my $blender = '/home/simone/blender/blender-3.1.0-linux-x64/blender -b /home/simone/some_file.blend --python /home/simone/blender_scripts/some_script.py';
my ($stdout, $stderr, $exit) = capture {
system( $blender );
};
print join "\n", "STDOUT", $stdout =~ s/Time/Foobar/rg;
print '-' x 80;
print join "\n", "STDERR", $stderr;
print '-' x 80;
這會產生正確的輸出,但是 - 據我所知 - 并沒有讓我看到它的進展。
這樣做:
my $out_fh = IO::File->new("out_stdout.txt", "w ");
my $err_fh = IO::File->new("out_stderr.txt", "w ");
capture { qx/$blender/ } stdout => $out_fh, stderr => $err_fh;
給我留下了兩個空檔案。這是我以后想看的兩個檔案。
我該怎么做?有沒有更好(即:可行)的方法?
uj5u.com熱心網友回復:
capture { qx/$blender/ } stdout => $out_fh, stderr => $err_fh;
應該
capture { system($blender) } stdout => $out_fh, stderr => $err_fh;
qx//導致輸出被捕獲,覆寫由創建的重定向capture { }。
例如,
use strict;
use warnings;
use Capture::Tiny qw( capture );
open( my $out_fh, '>', 'out' ) or die $!;
open( my $err_fh, '>', 'err' ) or die $!;
my $cmd = <<'EOS';
perl -e'$| = 1; while ( 1 ) { CORE::say $i; sleep 1; }'
EOS
my $e;
capture { system($cmd); $e = $?; } stdout => $out_fh, stderr => $err_fh;
die( "Killed by signal ".( $e & 0x7F )."\n" ) if $e & 0x7F;
die( "Exited with error ".( $e >> 8 )."\n" ) if $e >> 8;
$ perl a.pl &
[1] 19051
$ cat out
1
2
3
$ cat out
1
2
3
4
5
$ kill %1
但是您展示了自己正在處理腳本中的資訊。Capture::Tiny 不會幫助您做到這一點,至少在程式運行時不會。為此,您可以使用 IPC::Run。
use IPC::Run qw( run );
sub do_something_with_line {
print $_[0] =~ s/Time/Foobar/rg;
}
my $cmd = [ "perl", "-e", '$|=1; while ( 1 ) { CORE::say "Time ", $i; sleep 1; }' ];
my $buf = '';
run $cmd,
'>', sub {
$buf .= $_[0];
while ( $buf =~ s/^(.*\n)// ) {
do_something_with_line( $1 );
}
};
my $e = $?;
do_something_with_line( $buf ) if length( $buf );
die( "Killed by signal ".( $e & 0x7F )."\n" ) if $e & 0x7F;
die( "Exited with error ".( $e >> 8 )."\n" ) if $e >> 8;
$ perl b.pl
Foobar 1
Foobar 2
Foobar 3
Foobar 4
Foobar 5
^C
(添加'2>', ...以使用 stderr 執行某些操作。)
uj5u.com熱心網友回復:
system(或qx)運行命令完成然后回傳。您需要異步運行該命令。IPC::Run是我對此類互動的首選解決方案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/450430.html
標籤:perl
