如何捕获%ENV的更改?

时间:2009-03-25 23:50:48

标签: perl environment-variables

我有一堆运行工具流程的脚本。就像Makefile一样,但在Perl中。

作为这些流程的一部分,Perl脚本设置了环境变量,并且它们发生的时间并不总是很容易知道,因此很难重现流程的各个阶段。

有没有办法挂钩%ENV,这样我可以在环境变化时注册回调?

我可以绑它吗? %ENV已经表现得像个平局。

跟进:是的。你只需要与它结合。

5 个答案:

答案 0 :(得分:9)

嗷。我刚刚得到了我的屁股。无论如何,据说存在一个监视器包,它允许您通过绑定监视对现有变量的更改。这听起来像一个有趣的问题,所以当我开始深入研究The Blue Camel中的“tie”文档时,没有对现有变量发生什么的定义(即 - 是否保存了某个引用?)。所以,我用Google搜索“perl tie”现有变量“”。不幸的是,我发现的链接在社会上是不可接受的(盗版材料),所以我得到了相当多的打击,声誉明智。

祝你好运。

无论如何,只是为了澄清,它是在“高级Perl编程”的第9章,即“领带”一章。确保从信誉良好的网站购买副本: - )

答案 1 :(得分:4)

这是可行的。我认为执行以下操作可能会有性能损失,我确信我没有涵盖所有可能的情况,但这绝对可以让你开始。

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

答案 2 :(得分:2)

Variable::Magic似乎有效,但不像绑定的哈希,它似乎没有给你价值。

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

如果我稍后退出,它似乎正确地设置了环境变量,所以我不只是破坏%ENV

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

答案 3 :(得分:1)

我唯一能想到的是创建一个名为%ENVIRONMENT的绑定变量,它充当您可以挂钩的%ENV接口。然后使用,请确保始终使用%ENVIRONMENT而不是%ENV

答案 4 :(得分:1)

要尝试的另一件事是,在行之间进行读取:不要为要运行的任务调用“system(...)”,而是实现一个“my_system(...)”,它在调用外部任务之前打印出环境,以便可以使用命令行中的“env ...”命令重新创建其中一个任务

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