繁体   English   中英

使用 Capture::Tiny 将 STDOUT 捕获到文件

[英]Capture STDOUT to file with Capture::Tiny

我正在尝试使用 Capture::Tiny 将 STDOUT 捕获到一个文件中。

为了给你更大的图景,我的最终目标是:

  1. 在命令行上运行 Blender 进程
  2. 将日志捕获到文件句柄
  3. 观察文件句柄“增长”
  4. pipe 文件句柄的内容到 websocket 供用户通过 web 页面观看进度

我的计划是使用 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;

它产生了正确的 output 但是 - 据我所知 - 并没有让我看到它的进展。

这样做:

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;

给我留下两个空文件。 这是我稍后要看的两个文件。

我应该怎么做? 有更好的(即:可行的)方法吗?

capture { qx/$blender/ } stdout => $out_fh, stderr => $err_fh;

应该

capture { system($blender) } stdout => $out_fh, stderr => $err_fh;

qx//导致 output 被捕获,覆盖由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 执行某些操作。)

system (或qx )运行命令完成然后返回。 您需要异步运行命令。 IPC::Run是我对此类交互的首选解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM