2009-03-25 11 views
7

Mam kilka skryptów, które uruchamiają przepływy narzędzi. Tak jak plik Makefile, ale w Perlu.Jak mogę przechwycić zmiany w% ENV?

W ramach tych przepływów skrypty Perla ustawiają zmienne środowiskowe i nie zawsze łatwo jest określić, kiedy one się zdarzają, a zatem może być trudno odtworzyć poszczególne etapy przepływu.

Czy istnieje sposób, aby podłączyć się do% ENV, tak, że mogę zarejestrować wywołanie zwrotne, gdy zmienia się środowisko?

Czy mogę to tylko powiązać? % ENV już zachowuje się jak remis.

Kontynuacja: Tak. Po prostu się do tego przywiązujesz.

Odpowiedz

4

Jest to możliwe. Wydaje mi się, że za wykonanie poniższej czynności jest pewna kara za wydajność i jestem pewien, że nie omówiłem wszystkich możliwych przypadków, ale to zdecydowanie powinno zacząć.

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; 
} 
+0

Hmmm. Miły. Jeśli to działa, to znaczyłoby, że jedyną rzeczą magiczną w% ENV nie jest to, w jaki sposób jest ona zaimplementowana (to po prostu zwykły hasz), ale że ma odniesienie do budowania tablicy "char * env []" przez rzeczy które rozpoczynają procesy zewnętrzne. – Roboprog

1

Jedyne, co mogę wymyślić, to utworzyć powiązaną zmienną o nazwie %ENVIRONMENT, która działa jako interfejs do %ENV, do której można się podłączyć. Następnie użyj upewnij się, że zawsze używasz %ENVIRONMENT zamiast %ENV.

+0

hmm. Chciałem mieć możliwość modernizacji istniejącego kodu. Przepływy te mogą być bardzo tajemnicze. – mmccoo

+0

Cóż, pojawia się pytanie, jak często ciąg ENV pojawia się w twoim kodzie? Mam nadzieję, że nie często. Następnie można wykonać wyszukiwanie globalne na plikach i dodać remis w bloku BEGIN u góry. –

9

Ow. Właśnie złapałem tyłek. W każdym razie, istnieje podobno pakiet monitorów, który pozwala monitorować zmiany, poprzez remis, do istniejących zmiennych. To brzmiało jak interesujący problem, więc kiedy zacząłem zagłębiać się w dokument "tie" w The Blue Camel, nie było definicji tego, co dzieje się z istniejącą zmienną (tj. - czy gdzieś jest zapisane odniesienie?). Tak, szukałem w Google hasła "perl tie" istniejącej zmiennej "". Niestety, link, który znalazłem, był społecznie niedopuszczalny (piracki materiał), więc zostałem praktycznie spoliczkowany, a reputacja mądra.

Życzymy powodzenia.

W każdym razie, aby wyjaśnić, znajduje się w rozdziale 9 "Zaawansowanego programowania perlowego", rozdziału "Krawat". Upewnij się, że kupujesz kopię z renomowanej strony :-)

+0

Wysłałem pytanie do SO z pytaniem, co należy zrobić, a ty padłeś ofiarą cyber-linczu motłochu. Siriram umieścił swoje przykłady z tej książki na CPAN tutaj http://search.cpan.org/~sriram/examples/ i tutaj jest bezpośredni link do przykładu http://cpansearch.perl.org/src/SRIRAM/examples/ Tie/Monitor.pm –

+0

Edytuj swoją odpowiedź, a zacznę wracać z +1.BTW najlepsze linki do samej książki to http://oreilly.com/catalog/9780596004569/ (2nd edition) i http://oreilly.com/catalog/9781565922204/ (1st edition). –

+0

+1 za odrobinę odzysku, a ja zredagowałem, aby wyjaśnić tę książkę. Kolofonem w moim zaawansowanym programowaniu perlowym jest czarny lampart. Blue Camel Programming Perl (wielbłąd jest czarny, choć książka ma niebieskie wiązanie). – paxdiablo

2

Variable::Magic wydaje się działać, choć w przeciwieństwie do wiązanej hash, nie wydaje się, aby dać Ci wartość.

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'; 

A jeśli później bulić, wydaje się właściwie ustawić zmienną środowiskową, więc nie tylko sprać %ENV:

say `echo HOME=\$HOME`; 
say `echo HOME=%HOME%`; 
1

Inną rzeczą, aby spróbować, czytając między wierszami: zamiast wywoływania "systemu (...)" dla zadań do wykonania, zaimplementuj "mój_system (...)", który wypisuje środowisko przed wywołaniem zadania zewnętrznego, dzięki czemu możesz odtworzyć jedno z zadań za pomocą Komenda "env ..." z linii poleceń

# show the environment in which an external command runs: 
sub my_system 
    { 
    print map { $_ . "='" . $ENV{ $_ } . "'\n" } keys(%ENV); 
    print "'" . join("' '", @_) . "'\n"; 
    return system(@_); 
    }