编写持久的perl脚本

时间:2012-04-27 14:14:47

标签: linux perl bash unix

我正在尝试编写持久/缓存脚本。代码看起来像这样:

...
Memoize('process_fille');
print process_file($ARGV[0]);
...
sub process_file{
    my $filename = shift;
    my ($a, $b, $c) = extract_values_from_file($filename);
    if (exists $my_hash{$a}{$b}{$c}){
        return $my_hash{$a}{$b}{$c};
    }
    return $default;
}

将从循环中的shell脚本调用,如下所示

value=`perl my_script.pl`;

有没有办法可以调用这个脚本以保持其状态。从打电话到打电话。让我们假设初始化'%my_hash'和调用extract_values_from_file都是一项昂贵的操作。

谢谢

4 个答案:

答案 0 :(得分:10)

这是一种黑魔法,但您可以在脚本的__DATA__令牌之后存储状态并保留它。

use Data::Dumper; # or JSON, YAML, or any other data serializer
package MyPackage;
my $DATA_ptr;
our $state;
INIT {
    $DATA_ptr = tell DATA;
    $state = eval join "", <DATA>;
}

...
manipulate $MyPackage::state in this and other scripts
...

END {
    open DATA, '+<', $0;   # $0 is the name of this script
    seek DATA, $DATA_ptr, 0;
    print DATA Data::Dumper::Dumper($state);
    truncate DATA, tell DATA;  # in case new data is shorter than old data
    close DATA;
}
__DATA__
$VAR1 = {
    'foo' => 123,
    'bar' => 42,
    ...
}

INIT块中,存储文件__DATA__部分开头的位置并反序列化您的状态。在END块中,您重新序列化当前状态并覆盖脚本的__DATA__部分。当然,运行脚本的用户需要具有脚本的写权限。

编辑使用INIT块而不是BEGIN块 - 在编译阶段未设置DATA块。

答案 1 :(得分:6)

如果示例中的%my_hash在最终初始化状态下具有中等大小,您只需使用序列化模块之一,如StorableJSON::XSData::Dumper即可将数据保存在运行之间的组合形式。缺席时生成一个新文件,只要它存在就重新加载就绪内容。

另外,您已经提到过要在循环中调用此脚本。一个好的策略是不要在循环内立即调用脚本,而是构建一个参数队列,然后在单次执行循环之后将它们全部传递给脚本。脚本将设置其环境,然后循环遍历参数,轻松完成工作,而无需为每个参数重做设置步骤。

答案 2 :(得分:2)

你无法让脚本保持状态。一旦进程存在,任何未写入磁盘的信息都会消失。

有几种方法可以实现这一目标:

  • 编写一个侦听网络或unix套接字的守护进程。守护程序可以填充my_hash并回答从非常简单的my_script.pl发送的问题。它只需打开与守护进程的连接,发送问题并返回答案。

  • 创建高效的查找文件格式。如果您经常需要这些信息,它可能会保留在VFS缓存中。

  • 设置共享内存区域。脚本第一次启动时将信息保存在那里,然后再重新使用。但是,从Perl脚本开始,这可能很棘手。

答案 3 :(得分:0)

没有。不是直接的,但可以通过很多方式实现。

1) I understand **extract_values_from_file()** parses given file returning hash.
2) 1 can be made as a script, then dump the parsed hash using **Data::Dumper** into file.
3) When running my_script.pl, ensure that file generated by 2 is later than of the config file. Can achieve this via **make**
3.1) **use** the file generated by 2 to retrieve values.

通过冷冻/解冻可以实现同样的目的