Как я могу поймать изменения в% ENV? - PullRequest
7 голосов
/ 26 марта 2009

У меня есть куча скриптов, которые запускают потоки инструментов. Как Makefile, но в Perl.

В рамках этих потоков сценарии Perl устанавливают переменные среды, и не всегда легко узнать, когда они происходят, и, следовательно, может быть трудно воспроизвести отдельные этапы потока.

Есть ли способ подключиться к% ENV, чтобы я мог зарегистрировать обратный вызов при изменении среды?

Могу я просто привязаться к нему? % ENV уже ведет себя как галстук.

Продолжение: да. Вы просто привязываетесь к нему.

Ответы [ 5 ]

9 голосов
/ 26 марта 2009

Вл. Я только что зарыдала. В любом случае, предположительно существует пакет монитора, который позволяет вам отслеживать изменения посредством привязки к существующим переменным. Это звучало как интересная проблема, поэтому, когда я начал копаться в «связующей» документации в «Голубом верблюде», не было определения того, что происходит с существующей переменной (т. Е. Сохраняется ли ссылка где-нибудь?) Итак, я погуглил для "perl tie" существующей переменной "". К сожалению, ссылка, которую я нашел, была социально неприемлемой (пиратский материал), поэтому я потерял свою репутацию.

Удачи, хотя.

В любом случае, просто для пояснения, это в главе 9 «Расширенное программирование на Perl», в главе «Связывание». Убедитесь, что вы покупаете свою копию с уважаемого сайта: -)

4 голосов
/ 26 марта 2009

Это выполнимо. Я думаю, что, вероятно, есть снижение производительности за выполнение ниже, и я уверен, что я не охватил все возможные случаи, но это определенно должно помочь вам начать.

use strict;
use warnings;

tie %ENV, 'change_noticer', %ENV or die $!;

$ENV{PATH} .= ":test";
print $ENV{PATH}, "\n";
delete $ENV{PATH};

package change_noticer;

use strict;
use warnings;
use Carp;
use Tie::Hash;
use base 'Tie::StdHash';

sub DELETE {
    my $this = shift;

    carp "deleting \$ENV{$_[0]}";
    $this->SUPER::DELETE(@_);
}

sub STORE {
    my $this = shift;

    carp "altering \$ENV{$_[0]}";
    $this->SUPER::STORE(@_);
}

sub TIEHASH {
    my $class = shift;
    my $this  = bless {}, $class;

    while( my ($k,$v) = splice @_, 0, 2 ) {
        $this->{$k} = $v;
    }

    return $this;
}
2 голосов
/ 26 марта 2009

Переменная :: Магия , кажется, работает, хотя, в отличие от связанного хэша, она не дает вам значения.

use 5.010;
use Carp            qw<carp>;
use Variable::Magic qw<cast wizard>;

my $magic_hash = wizard store => sub { 
    carp "Hey! They're trying to set $_[-1]!"; 
};

cast %ENV, $magic_hash;

$ENV{HOME} = '~evilhacker';

И если я позже выложу оболочку, похоже, что она правильно установила переменную окружения, поэтому я не просто ударил %ENV:

say `echo HOME=\$HOME`;
say `echo HOME=%HOME%`;
1 голос
/ 27 марта 2009

Еще одна попытка, читая между строк: вместо вызова «system (...)» для запускаемых задач, реализуйте «my_system (...)», которая выводит окружение перед вызовом внешней задачи. , чтобы вы могли воссоздать одну из задач с помощью команды "env ..." из командной строки

# show the environment in which an external command runs:
sub my_system
    {
    print map { $_ . "='" . $ENV{ $_ } . "'\n" } keys( %ENV);
    print "'" . join( "' '", @_) . "'\n";
    return system( @_);
    }
1 голос
/ 26 марта 2009

Единственное, о чем я могу думать, - это создать связанную переменную с именем %ENVIRONMENT, которая действует как интерфейс к %ENV, к которому вы можете подключиться. Затем убедитесь, что вы всегда используете %ENVIRONMENT вместо %ENV.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...