目前在我的Perl脚本中,我进行了如下调用:
system(" ./long_program1 & ./long_program2 & ./long_program3 & wait ");
我希望能够在每个长时间运行的命令执行时记录,同时仍然执行它们异步。我知道系统调用导致perl生成一个fork,所以这样的事情可能吗?这可以被多个perl fork()和exec()调用替换吗?
请帮我找到更好的解决方案。
答案 0 :(得分:6)
是的,当然。您可以为每个要执行的程序分叉子进程。
您可以在分叉后执行system()
或exec()
,具体取决于系统调用完成后您希望Perl代码执行多少处理(因为exec()在功能上与{非常相似} {1}})
system(); exit $rc;
请注意,如果您需要做很多分叉,最好通过Parallel::ForkManager
控制它们,而不是手工分叉。
答案 1 :(得分:3)
两种选择:
use IPC::Open3 qw( open3 );
sub launch {
open(local *CHILD_STDIN, '<', '/dev/null') or die $!;
return open3('<&CHILD_STDIN', '>&STDOUT', '>&STDERR', @_);
}
my %children;
for my $cmd (@cmds) {
print "Command $cmd started at ".localtime."\n";
my $pid = launch($cmd);
$children{$pid} = $cmd;
}
while (%children) {
my $pid = wait();
die $! if $pid < 1;
my $cmd = delete($children{$pid});
print "Command $cmd ended at ".localtime." with \$? = $?."\n";
}
我使用open3
因为它比一个简单的fork
+ exec
更短,因为它不会将exec
错误归因于您发布的命令错误fork
+ exec
。
use threads;
my @threads;
for my $cmd (@cmds) {
push @threads, async {
print "Command $cmd started at ".localtime."\n";
system($cmd);
print "Command $cmd ended at ".localtime." with \$? = $?."\n";
};
}
$_->join() for @threads;