2

スクリプトが後で何度も実行されても、コードの一部を「最初に実行するときだけ」perlで1回だけ実行する方法

4

4 に答える 4

2

コードのその部分を、ifたとえばファイルを使用して、スクリプトの最初の実行であるかどうかをテストし、そうである場合にのみブロックを実行するブロック内に配置できます。

于 2012-12-25T21:37:44.570 に答える
2

考えられる方法の 1 つは、スクリプト自体を次のように書き直すことです。

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();

これは単なる概念です。残念ながら、ここでテストすることはできません。しかし、基本的な考え方は非常に単純です。スクリプト内で明確に区切られた「1 回実行」ブロックを作成し、最初に実行するときに、スクリプトのコンテンツからこのブロックを削除します。

于 2012-12-25T21:45:21.980 に答える
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ファイルを削除するだけで、あなたは黄金になります。

于 2012-12-26T08:41:57.807 に答える
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 自体をチェックする必要があります。

于 2012-12-25T22:18:58.860 に答える