如果代码的一部分只在perl中运行一次“第一次只执行”,即使脚本执行了很多次
答案 0 :(得分:2)
您可以将代码中的那部分放在某个if
块中,例如使用文件进行测试,无论是否是第一次执行脚本,如果是,只执行块。
答案 1 :(得分:2)
一种可行的方法是重写脚本本身,如下所示:
use warnings;
use script;
#### RUN ONCE BEGIN
do_something_once_only();
my $script_name = $0;
my $script_copy = $0 . 'old';
open my $fin, '<', $script_name or die $!;
open my $fout, '>', $script_copy or die $!;
my $script_content = do { local $/ = undef; <$fin>; };
$script_content =~ s/#### RUN ONCE BEGIN.+?#### RUN ONCE END/s;
print $fout $script_content;
`cp $script_copy $script_name`;
#### RUN ONCE END
do_something_else();
这只是一个概念;不幸的是,不能在这里测试它。但基本的想法很简单:你做了一个明确划定的“一次性运行”。在您的脚本中阻止,然后,在第一次执行时,从脚本的内容中删除此块。
答案 2 :(得分:1)
我会开发一个类对象,以非常清晰的英语来完成它的工作。在Ubuntu中,在/ var / run / [run_name] /下为脚本创建一个新目录,并在第一次运行时使用脚本在那里创建一个文件。例如:
文件名:RunOnce.pm
package RunOnce;
use Moose;
has 'run_name' => ( is => 'ro' , isa => 'Str' , required => 1 );
has 'initialize_file' => ( is => 'ro' , isa => 'Str'
, builder => '_build_initialize_file'
, lazy => 1 );
sub _build_initialize_file {
return '/var/run/'. $_[0]->run_name . '/run_once.txt';
}
sub is_initialized {
my $self = shift;
return ( -f $self->initialize_file );
}
sub initialize {
my $self = shift;
open(my $init_file,'>' . $self->initialize_file )
|| die "Could not open initialize file "
. $self->initialize_file . "! $!";
$self->process_initial_run();
print $init_file "Initialized on " . localtime(time) . "\n";
close($init_file);
}
sub process_initial_run {
warn "I don't do anything yet.";
}
package main;
my $runner = RunOnce->new(run_name => 'test_run');
$runner->initialize unless $runner->is_initialized();
1;
我刚在自己的盒子上测试过这个:
paul@paul-1204-virtualbox:~$ sudo rm -rf /var/run/test_run/
paul@paul-1204-virtualbox:~$ sudo mkdir /var/run/test_run/
paul@paul-1204-virtualbox:~$ sudo chown paul:paul /var/run/test_run
paul@paul-1204-virtualbox:~$ perl RunOnce.pm
I don't do anything yet. at RunOnce.pm line 29.
paul@paul-1204-virtualbox:~$ perl RunOnce.pm
paul@paul-1204-virtualbox:~$
现在你可以覆盖包和类并做你想做的事情,并且能够多次使用不同的项目,而不需要太多的工作:
新文件RunOnceOverride.pm:
package RunOnceOverride;
use Moose;
extends 'RunOnce';
sub process_initial_run {
warn "I'm going to try to do something else!";
}
package main;
my $runner = RunOnceOverride->new(run_name => 'test_run_override');
$runner->initialize unless $runner->is_initialized();
1;
现在:
paul@paul-1204-virtualbox:~$ sudo rm -rf /var/run/test_run_override/
paul@paul-1204-virtualbox:~$ sudo mkdir /var/run/test_run_override/
paul@paul-1204-virtualbox:~$ sudo chown paul:paul /var/run/test_run_override/
paul@paul-1204-virtualbox:~$ perl -I. RunOnceOverride.pm
I'm going to try to do something else! at RunOnceOverride.pm line 8.
paul@paul-1204-virtualbox:~$ perl -I. RunOnceOverride.pm
paul@paul-1204-virtualbox:~$
这是一个很好的可扩展的问题解决方案,但是初始化应该检查is_initialized本身,而不是期望主代码执行它。
答案 3 :(得分:1)
你不能做这样的事情:
mySub if (!(-e "/some/path/cpuid.txt"));
sub mySub() {
//do something
open(my $cpuid, ">", "/some/path/cpuid.txt") || die $!;
print $cpuid "blah";
}
顺便说一句,我不是任何形式的DRM的忠实粉丝。另外,你建议这样做的方式很容易打破。只需删除cpuid.txt文件就可以了。