Perl如何与正在运行的脚本进行交互?

时间:2010-09-01 12:44:36

标签: perl macos scripting file

我有一个Perl脚本,它运行一个不同的实用程序(对于那些感兴趣的人来说,称为Radmind),它具有编辑文件系统的能力。 Perl脚本监视此进程的输出,因此它将在整个情况下运行。

如果脚本运行的实用程序试图编辑脚本文件本身,即将其替换为较新版本,会发生什么? Perl是否在执行开始时加载脚本和任何链接库,然后忽略脚本文件本身,除非特别说明要搞乱它?或许,一切都会破裂,执行可能会或可能不会失败,具体取决于新文件与正在运行的文件有何不同?

或者其他可能完全不同?如果这属于SuperUser而道歉 - 对我来说似乎是个灰色区域。

6 个答案:

答案 0 :(得分:7)

它不像的那样简单,就像pavel的回答状态一样简单,因为Perl实际上没有“首先编译源代码然后运行编译代码”[1]的清晰划分,但是基本观点:在编译或执行该文件中的任何代码之前,每个源文件都是从磁盘中完整读取的,并且对源文件的任何后续更改都不会对正在运行的程序产生影响,除非您明确指示perl重新加载文件并执行新版本的代码[2]。

[1] BEGIN块将在编译期间运行代码,而evalrequire等命令将在运行时编译其他代码

[2]最有可能使用evaldo,因为requireuse检查文件是否已经加载,如果文件已经加载则忽略它。< / p>

答案 1 :(得分:3)

有趣的演示,请考虑

#! /usr/bin/perl

die "$0: where am I?\n" unless -e $0;

unlink $0 or die "$0: unlink $0: $!\n";

print "$0: deleted!\n";
for (1 .. 5) {
  sleep 1;
  print "$0: still running!\n";
}

示例运行:

$ ./prog.pl
./prog.pl: deleted!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!

答案 2 :(得分:2)

首先编译Perl脚本,然后运行;所以在运行时更改脚本不会改变正在运行的编译代码。

考虑这个例子:

#!/usr/bin/perl

use strict;
use warnings;

push @ARGV, $0;
$^I = '';

my $foo = 42;
my $bar = 56;

my %switch = (
    foo => 'bar',
    bar => 'foo',
);

while (<ARGV>) {
    s/my \$(foo|bar)/my \$$switch{$1}/;
    print;
}

print "\$foo: $foo, \$bar: $bar\n";

并在多次运行时观察结果。

答案 3 :(得分:0)

脚本文件一次读入内存。您可以在此之后从其他实用程序编辑文件 - 或者从Perl脚本本身编辑 - 如果您愿意的话。

答案 4 :(得分:0)

正如其他人所说,脚本被读入内存,编译并运行。 GBacon显示您可以删除该文件,它将运行。下面的代码显示您可以更改文件并do并获取新行为。

use strict;
use warnings;
use English qw<$PROGRAM_NAME>;

open my $ph, '>', $PROGRAM_NAME;
print $ph q[print "!!!!!!\n";];
close $ph;
do $PROGRAM_NAME;

......不要这样做!!!

答案 5 :(得分:0)

Perl脚本是简单的文本文件,它们被读入内存,在内存中编译,并且不再读取文本文件脚本。 (例外是在编译后进入词法范围的模块以及在某些情况下doeval语句......)

有一个众所周知的实用程序可以利用这种行为。查看CPAN及其许多版本,这些版本可能位于/ usr / bin目录中。您系统上的每个Perl版本都有一个CPAN版本。 CPAN将感知CPAN本身的新版本何时可用,询问您是否要安装它,如果您说“y”,它将下载较新版本并在您停止的地方重新生成,而不会丢失任何数据。

这个逻辑并不难理解。阅读/ usr / bin / CPAN,然后按照与$ Config :: Config {version}在您的系统上生成的相关的个性化版本。

干杯。