我有一个Perl脚本需要执行另一个Perl脚本。这个第二个脚本可以直接在命令行中执行,但是我需要从我的第一个程序中执行它。我需要传递一些通常在独立运行时传递的参数(第一个脚本定期运行,并在一定的系统条件下执行第二个脚本)。
初步Google搜索建议使用反引号或系统()调用。还有其他方法来运行吗? (我猜是的,因为我们正在讨论的Perl:P)如果我需要从调用的程序中捕获输出,那么最好使用哪种方法(如果可能的话,将输出管道输出到stdout,就像第二个程序被直接调用)?
(编辑:哦,现在我们提出一些相关的问题,This one是接近的,但不完全一样,第二个程序可能需要一个小时或更长时间才能运行(很多I / O),所以我’不确定一次性调用是否适合此选择。)
解决方法
您当前的perl解释器的位置可以在特殊变量$ ^ X中找到。如果perl不在您的路径中,或者如果您有多个可用的perl版本,但是要确保您全面使用相同的Perl版本,这一点非常重要。
执行外部命令时,包括其他Perl程序,确定它们是否真正运行可能相当困难。检查$?可以留下持久的精神伤疤,所以我更喜欢使用IPC::System::Simple(可从CPAN获得):
use strict; use warnings; use IPC::System::Simple qw(system capture); # Run a command,wait until it finishes,and make sure it works. # Output from this program goes directly to STDOUT,and it can take input # from your STDIN if required. system($^X,"yourscript.pl",@ARGS); # Run a command,and make sure it works. # The output of this command is captured into $results. my $results = capture($^X,@ARGS);
在上述两个示例中,您希望传递给外部程序的任何参数都可以转到@ARGS。在上述两个示例中也避免了shell,这样可以提供较小的速度优势,并避免涉及shell元字符的任何不必要的交互。上面的代码也期望你的第二个程序返回一个零退出值来表示成功;如果不是这样,您可以指定允许的退出值的另外的第一个参数:
# Both of these commands allow an exit value of 0,1 or 2 to be considered # a successful execution of the command. system( [0,1,2],$^X,@ARGS ); # OR capture( [0,2,@ARGS );
如果您有一个长期运行的过程,并且您希望在生成数据时处理其数据,那么您可能需要一个管道打开,或者是CPAN中更重的IPC模块之一。
说完所有这一切,任何时候你需要从Perl调用另一个Perl程序,你可能希望考虑如果使用模块是一个更好的选择。开始另一个程序在启动成本和在进程之间移动数据的I / O成本方面承担了相当多的间接费用。它也显着增加了错误处理的难度。如果您可以将外部程序转换为模块,您可能会发现它简化了整体设计。
祝一切顺利,
保罗