2012-04-27 5 views
4

Я пытаюсь написать постоянный/кэшированный скрипт. Код будет выглядеть примерно так:Написание персистентного скрипта perl

... 
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; 
} 

Какой будет вызываться из сценария оболочки в цикле следующим образом

value=`perl my_script.pl`; 

Есть ли способ, я мог бы назвать этот сценарий таким образом, что будет сохранять свое состояние. от вызова к вызову. Предположим, что инициализация «% my_hash» и вызов extract_values_from_file - дорогостоящая операция.

Thanks

+1

IMO зависит от того, как часто используется сценарий. Если он просто запускается время от времени, используйте метод сериализации. Если это больше, чем это, например, он служит какой-то важной, возможно, относительной цели в реальном времени, - делает ее постоянным фоновым сервером/использует IPC. – delicateLatticeworkFever

ответ

6

Если% my_hash в вашем примере имеет умеренный размер в своем окончательном инициализировано состоянии, вы можете просто использовать один из сериализации модулей как Storable, JSON::XS или Data::Dumper, чтобы сохранить ваши данные в предварительно собранном виде между пробегами. Создайте новый файл, когда он отсутствует, и просто перезагрузите готовый контент оттуда, когда он присутствует.

Кроме того, вы упомянули, что вы назовете этот скрипт в цикле. Хорошей стратегией было бы не сразу вызвать скрипт внутри цикла, а вместо этого построить очередь аргументов, а затем передать все из них сценарию после цикла в однократном выполнении. Script создаст свою среду, а затем зациклирует аргументы, делая свою легкую работу, без необходимости повторять шаги настройки для каждого из них.

2

Вы не можете заставить скрипт поддерживать свое состояние. Как только процесс существует, информация, не записанная на диск, отсутствует.

Есть несколько способов, вы можете сделать это, хотя:

  • Написать демон, который прослушивает сеть или сокет Unix. Демон может заполнить my_hash и ответить на вопросы, отправленные с очень простого my_script.pl. Ему нужно было только открыть соединение с демоном, отправить вопрос и ответить.

  • Создайте эффективный формат файла поиска. Если вам нужна информация часто, она, вероятно, останется в кэше VFS.

  • Настройте область общей памяти. При первом запуске ваших скриптов вы сохраняете информацию там, а затем повторно используете ее позже. Однако это может быть сложно из Perl-скрипта.

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. 

То же самое может быть достигнуто с помощью замораживания/оттаивания

8

Это вид темной магии, но вы можете сохранить состояние после вашего скрипта __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 block - блок DATA не настроен на этапе компиляции.

+5

Состояние сериализации - есть. Перепишите его внутри себя - большой проклятый НЕТ! Это может выглядеть забавно и давать +1 или два, но это полный беспорядок для поддержания. –

+3

Очень круто, но кажется нездоровым печатать в ваш файл исходного кода. – TLP

Смежные вопросы