我需要并行運行我的 perl 測驗,并在每個測驗檔案的單獨檔案中捕獲 STDOUT 和 STDERR。即使在一個檔案中捕獲,我也沒有成功。我到處都是,但沒有運氣。這是我開始的地方(我會為您省去所有的變化)。任何幫助是極大的贊賞。謝謝!
foreach my $file ( @files) {
next unless $file =~ /\.t$/;
print "\$file = $file\n";
$file =~ /^(\w )\.\w /;
my $file_pfx = $1;
my $this_test_file_name = $file_pfx . '.txt';
system("perl $test_dir\\$file > results\\$test_file_name.txt &") && die "cmd failed: $!\n";
}
uj5u.com熱心網友回復:
這是一個使用Parallel::ForkManager生成單獨行程的簡單示例。
在每個程序中STDOUT,STDERR流和流都被重定向,演示有兩種方式:STDOUT到一個變數,然后可以根據需要傳遞(這里轉儲到檔案中),以及STDERR直接到一個檔案。或者使用庫,并在單獨的代碼片段中提供示例。
這些數字1..6代表每個孩子將從中挑選以進行處理的資料批次。只有三個行程立即啟動,然后當一個行程完成時,另一個行程在它的位置啟動。? (這里他們幾乎立即退出,“作業”是微不足道的。)
use warnings;
use strict;
use feature 'say';
use Carp qw(carp)
use Path::Tiny qw(path);
use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new(3);
foreach my $data (1..6) {
$pm->start and next; # start a child process
proc_in_child($data); # code that runs in the child process
$pm->finish; # exit it
}
$pm->wait_all_children; # reap all child processes
say "\nParent $$ done\n";
sub proc_in_child {
my ($data) = @_;
say "Process $$ with data $data"; # still shows on terminal
# Will dump all that was printed to streams to these files
my (outfile, $errfile) =
map { "proc_data-${data}_" . $_ . ".$$.out" } qw(stdout stderr);
# Redirect streams
# One way to do it, redirect to a variable (for STDOUT)...
open my $fh_stdout, ">", \my $so or carp "Can't open handle to variable: $!";
my $fh_STDOUT = select $fh_stdout;
# ...another way to do it, directly to a file (for any stream)
# (first 'dup' it so it can be restored if needed)
open my $SAVEERR, ">&STDERR" or carp "Can't dup STDERR: $!";
open *STDERR, ">", $errfile or carp "Can't redirect STDERR to $errfile: $!";
# Prints wind up in a variable (for STDOUT) and a file (for STDERR)
say "STDOUT: Child process with pid $$, processing data #$data";
warn "STDERR: Child process with pid $$, processing data #$data";
close $fh_stdout;
# If needed to restore (not in this example which exits right away)
select $fh_STDOUT;
open STDERR, '>&', $SAVEERR or carp "Can't reopen STDERR: $!";
# Dump all collected STDOUT to a file (or pass it around, it's a variable)
path( $outfile )->spew($so);
return 1
}
雖然STDOUT被重定向到一個變數,STDERR但不能以這種方式重定向,在這里它直接轉到一個檔案。見打開。但是,也有一些方法可以將其捕獲在變數中。
然后您可以使用模塊從子行程回傳到父行程的能力,然后父行程可以處理這些變數。參見例如這篇文章和這篇文章和這篇文章。(還有更多,這些只是我所知道的。)或者實際上只是將它們轉儲到檔案中,就像這里所做的那樣。
另一種方法是使用可以運行代碼和重定向輸出的模塊,比如Capture::Tiny
use Capture::Tiny qw(capture);
sub proc_in_child {
my ($data) = @_;
say "Process $$ with data $data"; # on terminal
# Run code and capture all output
my ($stdout, $stderr, @results) = capture {
say "STDOUT: Child process $$, processing data #$data";
warn "STDERR: Child process $$, processing data #$data";
# return results perhaps...
1 .. 4;
}
# Do as needed with variables with collected STDOUT and STDERR
# Return to parent, or dump to file:
my ($outfile, $errfile) =
map { "proc_data-${data}_" . $_ . ".$$.out" } qw(stdout stderr);
path($outfile) -> spew( $stdout );
path($errfile) -> spew( $stderr );
return 1
}
?這會保持相同數量的行程在運行。或者,可以將其設定為等待整個批次完成,然后再開始另一批次。有關操作的一些詳細資訊,請參閱此帖子
uj5u.com熱心網友回復:
我認為,最簡單的方法是在“系統”命令中使用 shell 重定向。順便說一句,用'&'從中產生不受控制的子行程讓我皺眉。
這是一個帶有 shell 重定向和 fork 的簡單示例。
#!/usr/bin/perl
use strict;
for my $i (0..2) {
my $stdoutName = "stdout$i.txt";
my $stderrName = "stderr$i.txt";
my $pid = fork();
if($pid == 0) {
system("perl mytest.pl 1>$stdoutName 2>$stderrName"); #redirects are here 1> (stdout) and 2> (stderr)
exit $?;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/316633.html
