2009-03-25 38 views
7

Tengo un conjunto de scripts que ejecutan flujos de herramientas. Como hace un Makefile pero en Perl.¿Cómo puedo detectar cambios en% ENV?

Como parte de esos flujos, los scripts de Perl establecen entornos vars y no siempre es fácil saber cuándo ocurren y, por lo tanto, puede ser difícil reproducir etapas individuales del flujo.

¿Hay alguna forma de engancharme en% ENV para poder registrar una devolución de llamada cuando cambia el entorno?

¿Puedo unirme a él? % ENV ya se está comportando como un empate.

Seguimiento: Sí. Usted acaba de atarlo.

Respuesta

4

Esto es factible. Creo que probablemente haya una penalización en el rendimiento por hacer lo siguiente, y estoy seguro de que no cubrí todos los casos posibles, pero esto definitivamente debería comenzar.

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. Bonito. Si esto funciona, parecería implicar que lo único mágico sobre% ENV no es cómo se implementa (es solo un hash ordinario), sino que se hace referencia para construir la matriz "char * env []" por cosas que comiencen procesos externos. – Roboprog

1

Lo único que se me ocurre es crear una variable vinculada llamada %ENVIRONMENT que actúe como una interfaz para %ENV en la que pueda enganchar. Luego use asegúrese de usar siempre %ENVIRONMENT en lugar de %ENV.

+0

hmm. Quiero ser capaz de actualizar el código existente. Estos flujos pueden ser muy misteriosos – mmccoo

+0

Bueno, la pregunta es, ¿con qué frecuencia aparece la cadena ENV en su código? Ojalá no a menudo. A continuación, puede hacer una búsqueda global reemplazar en los archivos y agregar un empate en un bloque BEGIN en la parte superior. –

9

Ow. Acabo de darme un buen puntazo. De todos modos, supuestamente existe un paquete de monitor que le permite monitorear los cambios, a través del enlace, a las variables existentes. Esto sonaba como un problema interesante, así que cuando comencé a profundizar en la documentación de "empate" en The Blue Camel, no había definición de lo que le sucede a una variable existente (es decir, ¿se guardó una referencia en alguna parte?). SO, busqué en Google la variable existente "perl tie" "". Desafortunadamente, el enlace que encontré era socialmente inaceptable (material pirateado), así que me quitaron de la existencia, en cuanto a la reputación.

Buena suerte, sin embargo.

De todos modos, solo para aclarar, está en el capítulo 9 de "Programación avanzada de Perl", el capítulo sobre "Empate". Asegúrese de comprar su copia de un sitio acreditado :-)

+0

Publiqué una pregunta para ASÍ QUE pregunta qué se debe hacer y usted fue víctima de una mafia de ciber-linchamiento. Siriram ha puesto sus ejemplos de ese libro en CPAN aquí http://search.cpan.org/~sriram/examples/ y aquí está el enlace directo al ejemplo http://cpansearch.perl.org/src/SRIRAM/examples/ Tie/Monitor.pm –

+0

Edita tu respuesta y te iniciaré en tu camino de regreso con un +1.Por cierto, los mejores enlaces para el libro en sí son http://oreilly.com/catalog/9780596004569/ (2ª edición) y http://oreilly.com/catalog/9781565922204/ (1ª edición). –

+0

+1 por un poco de recuperación, y he editado para aclarar el libro. El colofón en mi Programación avanzada Perl es un leopardo negro. Blue Camel está programando Perl (el camello es negro, aunque el libro tiene encuadernación azul). – paxdiablo

2

Variable::Magic parece funcionar, aunque, a diferencia de un hash atado, no parece que le dará el valor.

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

Y si más tarde un shell, parece configurar correctamente la variable de entorno, por lo que no se limitó a Clobber %ENV:

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

Otra cosa a intentar, leyendo entre líneas: en vez de invocar "sistema (...)" para que se ejecuten las tareas, implemente un "mi_sistema (...)" que imprime el entorno antes de llamar a la tarea externa, para que pueda recrear una de las tareas con un comando "env ..." desde la línea de comando

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