2011-07-26 17 views

Respuesta

14

Los entornos secundarios no pueden cambiar los entornos principales. Su mejor apuesta es analizar env.sh desde dentro del código Perl y establecer las variables en %ENV:

#!/usr/bin/perl 

use strict; 
use warnings; 

sub source { 
    my $name = shift; 

    open my $fh, "<", $name 
     or die "could not open $name: $!"; 

    while (<$fh>) { 
     chomp; 
     my ($k, $v) = split /=/, $_, 2; 
     $v =~ s/^(['"])(.*)\1/$2/; #' fix highlighter 
     $v =~ s/\$([a-zA-Z]\w*)/$ENV{$1}/g; 
     $v =~ s/`(.*?)`/`$1`/ge; #dangerous 
     $ENV{$k} = $v; 
    } 
} 

source "env.sh"; 

for my $k (qw/foo bar baz quux/) { 
    print "$k => $ENV{$k}\n"; 
} 

Dado

foo=5 
bar=10 
baz="$foo$bar" 
quux=`date +%Y%m%d` 

imprime

foo => 5 
bar => 10 
baz => 510 
quux => 20110726 

El código sólo puede manejar archivos simples (por ejemplo, no maneja las declaraciones if o foo=$(date)). Si necesita algo más complejo, entonces escribir un contenedor para su script de Perl que ordene primero env.sh es la forma correcta de hacerlo (también es probablemente la manera correcta de hacerlo en primer lugar).

Otro motivo para obtener env.sh antes de ejecutar el script Perl es que la configuración de las variables de entorno en Perl puede ocurrir demasiado tarde para los módulos que esperan verlos.

En el archivo foo:

#!/bin/bash 

source env.sh 

exec foo.real 

donde foo.real es su script Perl.

2

Puede utilizar scripts de shell arbitrariamente complejos ejecutándolos con el shell relevante, volcando su entorno a la salida estándar en el mismo proceso y analizando eso en perl. Es prudente alimentar el resultado en algo que no sea% ENV o filtrar para valores de interés específicos, por lo que no cambia cosas como PATH que pueden tener efectos secundarios interesantes en otros lugares. He descartado la salida estándar y el error del script de shell generado, aunque podrían redirigirse a archivos temporales y utilizarse para la salida de diagnóstico en el script de Perl.

foo.pl:

#!/usr/bin/perl 
open SOURCE, "bash -c '. foo.sh >& /dev/null; env'|" or 
die "Can't fork: $!"; 

while(<SOURCE>) { 
if (/^(BAR|BAZ)=(.*)/) { 
    $ENV{$1} = ${2} ; 
} 
} 

close SOURCE; 

print $ENV{'BAR'} . "\n"; 

foo.sh: BAR exportación = Baz

+0

El uso de 'env' solo funciona si el script de shell exporta deliberadamente las variables. Si el script no los exporta específicamente, intente con 'set' en lugar de 'env'. – EdwinW

2

Prueba esto (ejemplo de código UNIX):

cd/tmp

vi s

#!/bin/bash 
export blah=test 

vi t

#!/usr/bin/perl 

if ($ARGV[0]) { 
    print "ENV second call is : $ENV{blah}\n"; 
} else { 
    print "ENV first call is : $ENV{blah}\n"; 
    exec(". /tmp/s; /tmp/t 1"); 
} 

chmod 777 s t

./ T

ENV primera llamada es:

ENV segunda llamada es: Prueba

El truco está usando el ejecutivo a la fuente primera de su escritura del golpe y después de llamar a su script de perl de nuevo con un argumento tan u conocer que te están llamando por segunda vez.

Cuestiones relacionadas