Как Perl взаимодействует со сценариями, которые он запускает? - PullRequest
6 голосов
/ 01 сентября 2010

У меня есть сценарий Perl, который запускает другую утилиту (для тех, кто интересуется Radmind ), которая может редактировать файловую систему.Сценарий Perl отслеживает выходные данные этого процесса, поэтому он будет работать во всей этой ситуации.

Что произойдет, если утилита, запускаемая сценарием, попытается отредактировать сам файл сценария, то есть заменить его наболее новая версия?Загружает ли Perl сценарий и любые связанные библиотеки в начале его выполнения, а затем игнорирует сам файл сценария, если специально не указано, что с ним связываться?Или, может быть, весь ад провалится, и выполнение может или не может завершиться неудачей в зависимости от того, насколько новый файл отличается от того, который запускается?

Или, может быть, что-то еще полностью?Извиняюсь, если это относится к SuperUser - мне кажется, что это серая область.

Ответы [ 6 ]

7 голосов
/ 01 сентября 2010

Это не совсем так просто, как в ответах Павла, потому что Perl на самом деле не имеет четкого разделения «сначала вы компилируете исходный код, затем запускаете скомпилированный код» [1], но базовая точка зрения: каждый исходный файл полностью считывается с диска до того, как какой-либо код в этом файле будет скомпилирован или выполнен, и любые последующие изменения в исходном файле не будут влиять на работающую программу, если вы не указали perl повторно загрузить файл и выполнить код новой версии [2].

Блоки

[1] BEGIN будут выполнять код во время компиляции, в то время как такие команды, как eval и require, будут компилировать дополнительный код во время выполнения

[2] Скорее всего, с помощью eval или do, поскольку require и use проверяют, был ли файл уже загружен, и игнорируют его, если он есть.

3 голосов
/ 01 сентября 2010

Для забавной демонстрации рассмотрим

#! /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: deleted!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!
./prog.pl: still running!
2 голосов
/ 01 сентября 2010

Ваш Perl-скрипт будет сначала скомпилирован, а затем запущен;поэтому изменение сценария во время его работы не изменит скомпилированный код.

Рассмотрим следующий пример:

#!/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";

и просмотрите результат при многократном запуске.

0 голосов
/ 01 сентября 2010

Скрипты Perl - это простые текстовые файлы, которые считываются в память, компилируются в памяти, и скрипт текстового файла больше не читается.(Исключением являются модули, которые входят в лексическую область видимости после компиляции, а в некоторых случаях операторы do и eval ...)

Существует хорошо известная утилита, которая использует это поведение.Посмотрите на CPAN и его многочисленные версии, которые, вероятно, находятся в вашем каталоге / usr / bin.Существует версия CPAN для каждой версии Perl в вашей системе.CPAN почувствует, когда будет доступна новая версия самого CPAN, спросит, хотите ли вы установить его, и если вы скажете «y», он загрузит более новую версию и возродится сам там, где вы остановились, без потери каких-либо данных.

Логика этого не сложна для подражания.Прочтите / usr / bin / CPAN, а затем следуйте индивидуальным версиям, связанным с тем, что $ Config :: Config {version} будет генерировать в вашей системе.

Cheers.

0 голосов
/ 01 сентября 2010

Как говорили другие, скрипт считывается в память, компилируется и запускается.GBacon показывает, что вы можете удалить файл, и он запустится.Этот код ниже показывает, что вы можете изменить файл и do его и получить новое поведение.

use strict;
use warnings;
use English qw<$PROGRAM_NAME>;

open my $ph, '>', $PROGRAM_NAME;
print $ph q[print "!!!!!!\n";];
close $ph;
do $PROGRAM_NAME;

... НЕ ДЕЛАЙТЕ ЭТОГО !!!

0 голосов
/ 01 сентября 2010

Файл сценария считывается один раз в память.Вы можете отредактировать файл из другой утилиты после этого - или из самого скрипта Perl - если хотите.

...