2011-07-26 9 views

Répondre

14

Les environnements enfants ne peuvent pas modifier les environnements parents. Votre meilleur pari est d'analyser env.sh à l'intérieur du code Perl et définir les variables %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"; 
} 

Étant donné

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

imprime

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

Le code ne peut traiter des fichiers simples (par exemple, il ne gère pas les instructions if ou foo=$(date)). Si vous avez besoin de quelque chose de plus complexe, alors écrire d'abord un wrapper pour votre script Perl qui utilise les sources env.sh est la bonne façon d'y aller (c'est aussi probablement la bonne façon d'y aller en premier lieu). Une autre raison de source env.sh avant d'exécuter le script Perl est que la définition des variables d'environnement en Perl peut arriver trop tard pour les modules qui attendent de les voir.

Dans le fichier foo:

#!/bin/bash 

source env.sh 

exec foo.real 

où foo.real est votre script Perl.

2

Vous pouvez utiliser des scripts shell arbitrairement complexes en les exécutant avec le shell correspondant, en déchargeant leur environnement sur la sortie standard dans le même processus et en analysant cela dans perl. Nourrir la sortie dans autre chose que% ENV ou filtrer pour des valeurs spécifiques d'intérêt est prudent afin de ne pas changer des choses comme PATH qui peuvent avoir des effets secondaires intéressants ailleurs. J'ai supprimé la sortie standard et l'erreur du script shell généré, bien qu'ils puissent être redirigés vers des fichiers temporaires et utilisés pour la sortie de diagnostic dans le script 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: export BAR = baz

+0

L'utilisation de 'env' ne fonctionne que si le script shell exporte délibérément les variables. Si le script ne les exporte pas spécifiquement, essayez 'set' au lieu de 'env'. – EdwinW

2

Essayez ceci (exemple de code 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 premier appel est:

ENV deuxième appel est: Test

L'astuce utilise l'exécutif à la source de votre script bash d'abord, puis d'appeler votre script Perl à nouveau avec un argument si tu sais que vous êtes appelé pour une deuxième fois.

Questions connexes