在不重启Ubuntu的情况下全局设置环境变量

28
我知道可以通过将条目添加到系统范围内的环境变量来设置环境变量。
/etc/environment
或者
/etc/profile

但这需要系统重启或 X 重启。

在 Ubuntu / Linux 中是否可能设置环境变量,以便立即在整个系统范围内可用,而无需重新启动操作系统或注销用户?


一次 X 重启已经足够了,为什么你还想要进行系统重启呢? - fge
好的,我不想进行系统重启。这就是整个问题所在。 - Abhijeet Pathak
1
这意味着你不能做你所要求的事情,那么:你至少需要重新启动X。你无法更改已经运行的进程的环境。 - fge
1
@fge 实际上你是可以的,但需要用 gdb 连接到该进程。虽然它可以工作,但这种方法很不正规。 - SiegeX
3个回答

18
简短的回答是:一般情况下你是做不到这个的为什么没有一般性的解决方案? “为什么?”需要更详细的解释。在Linux中,环境是进程特定的。每个进程的环境都存储在专门为该进程分配的特殊内存区域中。
引用:

顺便说一句:要快速查看进程环境,请查看/proc/<pid>/env(或尝试/proc/self/env 查看当前正在运行的进程的环境,例如您的shell)。

当一个(“父”)进程启动另一个(“子”)进程(通过fork(2)),父进程的环境被复制以生成子进程的环境。此后这两个环境之间没有继承式的关联,它们是完全独立的。所以我们不能改变“全局”或“主”环境,来实现你想要的目标。
为什么不直接更改所有正在运行进程的每个进程环境?环境的内存区域位于一个定义良好的位置(基本上就在分配给堆栈的内存之前),因此你不能轻易地扩展它,因为这会破坏进程的其他关键内存区域。 特殊情况下的可能解决方案 也就是说,我们可以想象几种特殊情况,在这些情况下你确实可以实现你想要的目标。
  • 最明显的是,如果你进行“大小中性”的更改,你可以修补所有进程的所有环境。例如,将每个存在的USER=foo环境变量替换为USER=bar。我担心这是一种非常特殊的情况。

  • 如果你不需要更改所有进程的环境,而只需要更改某个已知类别的进程环境,那么可能可以采用更有创意的方法。Vorsprung的回答 是使用仅Bash进程做到这一点的一个令人印象深刻的演示。

可能还有许多其他特殊情况,存在可能的解决方案。但如上所述:对于一般情况没有解决方案。


14

这个 Perl 程序使用 gdb 来将所有当前正在运行的 bash shell 中的 USER 变量更改为给定的程序参数。要设置一个新变量,可以使用内部的 bash 调用 "set_if_not"。

#!/usr/bin/perl

use strict;
use warnings;

my @pids = qx(ps -C bash -o pid=);
my $foo  = $ARGV[0];
print "changing user to $foo";
print @pids;

open( my $gdb, "|gdb" ) || die "$! gdb";
select($gdb);
$|++;
for my $pid ( @pids ) {
    print "attach $pid\n";
    sleep 1;
    print 'call bind_variable("USER","' . $foo . '",0)' . "\n";
    sleep 1;
    print "detach\n";
}

这个方法只适用于bash(我只在Ubuntu 10.04 LTS上的4.1版本进行了测试),并且不会影响已经在运行的程序。很明显,它必须以root权限运行。


为什么需要root权限? - osgx
2
@osgx 的含义是必须更改在系统上运行的所有 shell 中的变量。要更改所有用户的进程,显而易见的做法是成为 root 用户。 - Vorsprung
绝对赞成!它可以简化一点。可以使用 ps -C bash -o pid= 来消除 PID 标题行。然后可以使用 @pid 代替 @pids[1..$#pids] - TrueY
@TrueY 或者我可以使用“shift(@pids)”来实现tmtowtdi :) - Vorsprung
当然可以!但是不编写头文件更有效。而且只需要一个额外的=就可以了。 - TrueY
显示剩余7条评论

2

我担心这里的解决方案会让人感到沮丧:不要使用环境变量,而是使用文件。

因此,不要像设置/etc/environment一样:

SPECIAL_VAR='some/path/I/want/later/'

并且使用以下方式调用:

$SPECIAL_VAR

请在 ~/.yourvars 中创建一个文件,并将以下内容写入:

SPECIAL_VAR='some/path/I/want/later/'

并且每次需要变量时都要源化(source)它:
cd `source ~/.yourvars; echo $SPECIAL_VAR`

一个黑客?也许吧。但它有效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接