我对设置一个外壳实例与另一个外壳实例的环境变量感兴趣。所以我决定做一些研究。阅读了许多与此有关的问题后,我决定对其进行测试。
我生成了两个正在运行的外壳A和B(PID 420)zsh
。从外壳程序AI运行以下命令。
sudo gdb -p 420
(gdb) call setenv("FOO", "bar", 1)
(gdb) detach
从外壳B运行时,env
我可以看到变量FOO确实设置为bar值。这使我认为FOO已在外壳B的环境中成功初始化。但是,如果我尝试打印FOO,则会出现一个空行,表明未设置FOO。对我来说,这里似乎有矛盾。
这已在我自己的Arch GNU / Linux系统和Ubuntu VM上进行了测试。我还在bash
变量甚至未在env中显示的地方对此进行了测试。这虽然使我感到失望,但如果shell在生成时缓存其环境的副本并仅使用它(在链接的问题之一中建议),则是有道理的。这仍然不能回答为什么zsh
可以看到变量。
为什么输出为echo $FOO
空?
输入注释后,我决定进行更多测试。结果可以在下表中看到。在第一列中是将FOO
变量注入到的外壳。第一行包含该命令的输出,该命令的输出可以在其下面看到。FOO
使用:注入变量sudo gdb -p 420 -batch -ex 'call setenv("FOO", "bar", 1)'
。特定于zsh:的命令zsh -c '...'
也已使用bash进行了测试。结果是相同的,为简洁起见,省略了它们的输出。
| | env | grep FOO | echo $FOO | zsh -c 'env | grep FOO' | zsh -c 'echo $FOO' | After export FOO |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh | FOO=bar | | FOO=bar | bar | No Change |
| bash | | bar | | | Value of FOO visible in all tests |
| | env | grep FOO | echo $FOO | zsh -c 'env | grep FOO' | zsh -c 'echo $FOO' | After export FOO |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh | FOO=bar | | FOO=bar | bar | No Change |
| bash | | bar | | | Value of FOO visible in all tests |
以上似乎暗示结果是不可知的分布。这并不能告诉我更多,zsh
并且可以bash
不同地处理变量的设置。此外,export FOO
在这种情况下,根据外壳的不同,其行为也有很大不同。希望这些测试可以使其他人明白。
大多数弹不使用getenv()
/ setenv()
/ putenv()
API。
启动时,它们为收到的每个环境变量创建shell变量。这些将存储在内部结构中,这些内部结构需要携带其他信息,例如变量是否已导出,只读……它们不能environ
为此使用libc 。
同样,因为这个原因,他们不会使用execlp()
,execvp()
执行命令,但拨打execve()
直接系统调用,计算envp[]
基于其输出变量的名单上排列。
因此,在您的中gdb
,您需要在该Shell内部变量表中添加一个条目,或者可能调用正确的函数,该函数将使其解释export VAR=value
为它自己更新该表的代码。
至于为什么你看到之间的差异bash
,并zsh
当你调用setenv()
的gdb
,我怀疑那是因为你所呼叫setenv()
的外壳初始化之前在进入,例如main()
。
您会注意到,bash
'smain()
是int main(int argc, char* argv[], char* envp[])
(并bash
从中映射那些env vars中的变量envp[]
),而zsh
's是int main(int argc, char* argv[])
并zsh
从中获取变量environ
。setenv()
确实会修改,environ
但不能envp[]
就地修改(在多个系统上为只读,以及这些指针指向的字符串)。
无论如何,environ
在启动后读取外壳程序之后,使用setenv()
将无效,因为外壳程序之后将不再使用environ
(或getenv()
)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句