找出一个命令使用了哪些环境变量

17
在Linux环境下(我的情况是XUbuntu),是否有一种方法可以找出从控制台运行的命令访问了哪些环境变量?必须有一种方法可以找到这些变量,因为有人必须向程序提供值。但是是否有默认方法来执行此操作?在这里所说的程序是xprintidle。
4个回答

21
假设你想要获取某个进程运行命令时实际使用的变量,你可以使用 ltrace 并查找对 getenv 的调用:
$ ltrace -e getenv ./your_program

当然,对于getenv的参数可以进行计算(因此你无法真正预测它)。
然而,一些(旧的或奇怪的)应用程序可能会使用全局的environ,或者是main的第三个可选参数;一些应用程序甚至会使用putenvsetenvunsetenv来更改其环境变量(这三个都是libc函数,而不是shell内置函数)。
但是,xprintidle主要与Xorg服务器交互。我很惊讶你期望它使用很多环境变量(除了DISPLAY)。

这种方式似乎是可行的,但有一个问题:没有调用getenv,但我确定访问了一个环境变量(在库调用中)。然而,使用strace,我得到了“execve("/usr/bin/xprintidle",["xprintidle"],[/* 41 vars */])”作为第一个调用。这是否意味着变量不是通过getenv获取的? - Jost
1
不 -- execve() 是程序执行的唯一方式(execl() 和其他函数只是它的包装器),它的第三个参数是一个指向所有环境变量的指针数组。你会在每个执行程序的 strace 中看到这个调用。 - fge
我提到的是 ltrace 而不是 strace;它们不一样! - Basile Starynkevitch
1
在某些情况下,对getenv进行ltrace会起作用,但是请注意,如果您正在尝试跟踪基于C的编程语言中的库调用,则需要小心。在Python 2.7和Perl 5.8.5中打印环境变量$USER不会执行getenv。尝试ltrace -o log -f perl -e 'print $ENV{"USER"};' > & /dev/null && grep getenv log | egrep '\bUSER\b'或者ltrace -o log -f python -c 'import os;print os.environ["USER"]' > & /dev/null && grep getenv log | egrep '\bUSER\b' - Ross Rogers

3

您是指实际访问还是进程的定义环境变量?

对于定义的环境变量,您可以使用:

perl -pe 's,\00,\n,g' /proc/xxxx/environ

这里的xxxx是您的进程PID。

对于已访问的变量,您需要使用类似ltrace的工具,并检查是否存在getenv()调用。


“ltrace” 对你没有帮助,因为真的没有任何理由调用 “getenv()”。 - Šimon Tóth
嗯?如果你想要访问环境变量的值,你必须调用getenv() - fge
大多数程序使用getenv访问环境,因此跟踪它通常(但并非总是)有帮助。请参见我的答案。一些程序可以使用environmain的第三个参数获取环境变量。实际上很少有程序这样做! - Basile Starynkevitch
@BasileStarynkevitch 为什么要调用 getenv?如果你打算 fork 并且不想干扰环境数组,那么肯定会调用 setenv,但是 getenv 呢? - Šimon Tóth
@Let_Me_Be:你的意思是putenv,而不是getenvgetenv在许多程序中都很常用,例如ls - 可以看 http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c 等等- 它用于 QUOTING_STYLECOLUMNSLS_BLOCK_SIZE、环境变量等。 - Basile Starynkevitch

1

您可以使用printenv命令查看传递给程序的环境变量。

程序查看其环境的一种方式是使用getenv调用,因此您可以使用跟踪程序或LD_PRELOAD技巧来包装该调用并找出它们正在寻找什么。

但是,并非所有程序都使用getenv来查看其环境。如果程序使用以下(不常见)格式的主函数,则可以通过envp指针查看环境变量:

int main(int argc, char *argv[], char *envp[]) {
    /* ... */
}

此外,程序可以通过environ变量访问环境。

您可能会通过跟踪getenv调用来获得成功,但这并不是保证——它因程序而异。


-1
如果您想获取环境变量列表,可以使用env命令来完成。
但是,确定程序访问了哪些变量是不可能的,因为它们都是按原样传递的。

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