我有一个运行Perl脚本的工具(叫做Radmind,对于那些感兴趣的人来说),它有修改文件系统的能力。Perl脚本监视此进程的输出,因此在整个过程中它将一直运行。
如果工具试图编辑脚本文件本身,例如用新版本替换它,会发生什么情况呢?Perl是否在执行开始时加载脚本和任何链接库,然后忽略脚本文件本身,除非明确告知要操作它?或者,所有东西都乱了,可能会根据新文件与正在运行的文件的差异而失败或成功?
或者也许是其他完全不同的情况?如果这篇文章不适合,请谅解——对我来说似乎是一个灰色地带。
perl
重新加载文件并执行新版本的代码[2],否则不会影响正在运行的程序。
[1] BEGIN
块将在编译期间运行代码,而像eval
和require
这样的命令将在运行时编译额外的代码。
[2] 最可能使用eval
或do
,因为require
和use
会检查文件是否已经加载,并在已加载时忽略它。
为了一个有趣的演示,请考虑
#! /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:已删除! ./prog.pl:仍在运行! ./prog.pl:仍在运行! ./prog.pl:仍在运行! ./prog.pl:仍在运行! ./prog.pl:仍在运行!
#!/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";
并且在多次运行时观察结果。
正如其他人所说,脚本被读入内存,编译并运行。GBacon表明您可以删除文件并运行它。下面的代码显示您可以更改文件并执行它以获取新的行为。
use strict;
use warnings;
use English qw<$PROGRAM_NAME>;
open my $ph, '>', $PROGRAM_NAME;
print $ph q[print "!!!!!!\n";];
close $ph;
do $PROGRAM_NAME;
...不要这样做!!!
脚本文件只需读取一次即可加载到内存中。之后,您可以从其他实用程序或Perl脚本本身编辑该文件(如果需要)。
do
和eval
语句...)。
BEGIN
块中它将被包含在程序中。至少在我目前可以访问的perl版本中,它不会在开始解析之前读取整个文件,并且BEGIN
块会在解析到闭合括号时立即执行。这种行为可能与操作系统有关。 - Ven'Tatsu