2009-03-25 5 views
7

Ich habe eine Reihe von Skripten, die Werkzeugflüsse ausführen. Wie ein Makefile nur in Perl.Wie kann ich Änderungen an% ENV abfangen?

Als Teil dieser Abläufe setzen die Perl-Skripte die Umgebung vars und es ist nicht immer einfach zu wissen, wann sie auftreten und daher kann es schwierig sein, einzelne Stufen des Ablaufs zu reproduzieren.

Gibt es eine Möglichkeit, sich in% ENV einzuklinken, sodass ich einen Rückruf registrieren kann, wenn sich die Umgebung ändert?

Kann ich nur daran binden? % ENV verhält sich bereits wie eine Krawatte.

Follow-up: Ja. Sie binden sich einfach daran.

Antwort

4

Dies ist machbar. Ich denke, es gibt wahrscheinlich eine Leistungseinbuße, um das Folgende zu tun, und ich bin mir sicher, dass ich nicht alle möglichen Fälle behandelt habe, aber das sollte dich definitiv weiterbringen.

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. Nett. Wenn das funktioniert, dann scheint es, dass das einzige, was magisch an% ENV ist, nicht wie es implementiert ist (es ist nur ein gewöhnlicher Hash), sondern dass es referenziert wird, um das Array "char * env []" nach Dingen aufzubauen das starten externe Prozesse. – Roboprog

1

Das einzige, was ich denken kann, ist eine gebundene Variable mit dem Namen %ENVIRONMENT zu erstellen, die als Schnittstelle zu %ENV dient, in die Sie einhaken können. Stellen Sie dann sicher, dass Sie immer %ENVIRONMENT anstelle von %ENV verwenden.

+0

hmm. Ich möchte irgendwie vorhandenen Code nachrüsten können. Diese Flüsse können sehr mysteriös sein. – mmccoo

+0

Nun, die Frage wird dann, wie oft erscheint die Zeichenfolge ENV in Ihrem Code? Hoffentlich nicht oft. Sie könnten dann eine globale Suche durchführen, um die Dateien zu ersetzen und eine Verknüpfung in einem BEGIN-Block oben hinzuzufügen. –

9

Ow. Ich habe gerade meinen Hintern gejubelt. Wie auch immer, es gibt angeblich ein Monitor-Paket, mit dem Sie Änderungen über vorhandene Variablen überwachen können. Das hörte sich nach einem interessanten Problem an, und als ich anfing, mich in der "tie" -Dokumentation in The Blue Camel zu vertiefen, gab es keine Definition dafür, was mit einer vorhandenen Variablen passiert (d. H. - wird eine Referenz irgendwo gespeichert?). SO, ich googelte für "Perl Tie" existierende Variable "". Leider war der Link, den ich fand, gesellschaftlich inakzeptabel (raubkopiertes Material), so dass ich so ziemlich aus dem Leben gerissen wurde, was den Ruf betrifft.

Viel Glück, obwohl.

Wie auch immer, nur um zu klären, es ist in Kapitel 9 von "Advanced Perl Programming", das Kapitel auf "Tie". Stellen Sie sicher, dass Sie Ihre Kopie von einer seriösen Website kaufen :-)

+0

Ich habe eine Frage an SO gestellt, in der ich gefragt habe, was getan werden sollte und du wurdest Opfer eines Cyber-Lynch-Mobs. Siriram hat seine Beispiele aus diesem Buch über CPAN hier http://search.cpan.org/~sryram/examples/ gestellt und hier ist der direkte Link zum Beispiel http://cpansearch.perl.org/src/SRIRAM/examples/ Tie/Monitor.pm –

+0

Bearbeiten Sie Ihre Antwort und ich werde Sie auf Ihrem Weg zurück mit einem +1 beginnen.Übrigens sind die besten Links für das Buch selbst http://oreilly.com/catalog/9780596004569/ (2. Ausgabe) und http://oreilly.com/catalog/9781565922204/ (1. Ausgabe). –

+0

+1 für ein bisschen Erholung, und ich bearbeitet, um das Buch zu klären. Das Kolophon in meinem Advanced Perl Programming ist ein schwarzer Leopard. Blue Camel programmiert Perl (das Kamel ist schwarz, obwohl das Buch blau gebunden ist). – paxdiablo

2

Variable::Magic scheint zu stehen, obwohl im Gegensatz zu einer gebundenen Hash, es scheint nicht Ihnen den Wert zu geben.

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

Und wenn ich später heraus schälen, so scheint es richtig die Umgebungsvariable gesetzt, so dass ich nicht nur %ENV clobber:

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

Eine andere Sache zu versuchen, zwischen den Zeilen zu lesen: statt Um "system (...)" für auszuführende Tasks aufzurufen, implementieren Sie ein "my_system (...)", das die Umgebung vor dem Aufruf der externen Task ausgibt, so dass Sie eine der Tasks mit einem neu erstellen können "env ..." Befehl von der Befehlszeile

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