如何在Perl脚本中运行Perl脚本?

cbo*_*wns 25 perl ipc

我有一个需要执行另一个Perl脚本的Perl脚本.第二个脚本可以直接在命令行上执行,但我需要在第一个程序中执行它.我需要传递一些参数,这些参数通常在它独立运行时传递(第一个脚本定期运行,并在一组系统条件下执行第二个脚本).

Google的初步搜索建议使用反引号或system()调用.有没有其他方法来运行它?(我猜是的,因为它是我们正在讨论的Perl:P)如果我需要从被调用的程序中捕获输出,那么首选哪种方法(如果可能的话,将输出管道输出到stdout,就像第二次一样程序被直接调用)?

(编辑:哦,现在 SO提出了一些相关问题.这个问题很接近,但与我提出的问题并不完全相同.第二个程序可能需要一个小时或更长时间才能运行(大量I/O),所以我不确定一次性调用是否适合这种情况.)

Axe*_*man 32

你可以做到.

{
    local @ARGV = qw<param1 param2 param3>;
    do '/home/buddy/myscript.pl';
}
Run Code Online (Sandbox Code Playgroud)

防止在另一个perl副本中加载的开销.


pjf*_*pjf 31

您当前的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, wait until it finishes, and make sure it works.
# The output of this command is captured into $results.
my $results = capture($^X, "yourscript.pl", @ARGS);
Run Code Online (Sandbox Code Playgroud)

在上面的两个示例中,您希望传递给外部程序的任何参数都会进入@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, "yourscript.pl", @ARGS );
 # OR
 capture( [0,1,2, $^X, "yourscript.pl", @ARGS );
Run Code Online (Sandbox Code Playgroud)

如果您有一个长时间运行的进程并且想要在生成数据处理它的数据,那么您可能需要管道打开,或者需要CPAN中的一个更重量级的IPC模块.

说了这么多,每当你需要从Perl调用另一个Perl程序时,你可能希望考虑使用模块是否是更好的选择.启动另一个程序会带来相当多的开销,包括启动成本和在进程之间移动数据的I/O成本.它还显着增加了错误处理的难度.如果您可以将外部程序转换为模块,您可能会发现它简化了整体设计.

祝一切顺利,

保罗


inn*_*naM 12

你已经对你的问题得到了很好的答案,但总是有可能采取不同的观点:也许你应该考虑重构你想从第一个脚本运行的脚本.将功能转换为模块.使用第一个和第二个脚本中的模块.


Col*_*lin 11

我可以想到几种方法来做到这一点.你已经提到了前两个,所以我不会详细介绍它们.

  1. 反引号:$ retVal =``perl somePerlScript.pl ;
  2. system()调用
  3. EVAL

eval可以通过将另一个文件压入字符串(或字符串列表),然后'评估'字符串来完成.下面是一个样本:

#!/usr/bin/perl
open PERLFILE, "<somePerlScript.pl";
undef $/;   # this allows me to slurp the file, ignoring newlines
my $program = <PERLFILE>;
eval $program;
Run Code Online (Sandbox Code Playgroud)

4.做:

do 'somePerlScript.pl'

  • 简单地使用“do”不是更容易和更简洁吗? (2认同)

Jon*_*ler 6

如果需要捕获命令的输出,请使用反引号.

使用system如果你不需要捕获命令的输出.

TMTOWTDI:所以还有其他方法,但这些是最容易和最可能的两种方式.


Ren*_*uis 6

如果您需要异步调用外部脚本 - 您只想启动它而不是等待它完成 - 那么:

# On Unix systems, either of these will execute and just carry-on
# You can't collect output that way
`myscript.pl &`;
system ('myscript.pl &');    

# On Windows systems the equivalent would be
`start myscript.pl`;
system ('start myscript.pl');

# If you just want to execute another script and terminate the current one
exec ('myscript.pl');
Run Code Online (Sandbox Code Playgroud)


bri*_*foy 5

有关进程间通信的几个选项,请参阅perlipc文档.

如果您的第一个脚本仅为第二个脚本设置环境,那么您可能正在寻找exec.