![Unix shell 变量中“exported”的范围是什么?](https://linux22.com/image/1444621/Unix%20shell%20%E5%8F%98%E9%87%8F%E4%B8%AD%E2%80%9Cexported%E2%80%9D%E7%9A%84%E8%8C%83%E5%9B%B4%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F.png)
我已经按照以下方式设置了一些环境变量:
MY_VAR='helloworld'
export MY_VAR
然后我通过以下方式切换到另一个用户
su SOME_OTHER_USER
我回应了 MY_VAR 变量..并且看到了它的值!
1) 您能解释一下这个问题吗?据我所知,当我通过 export 命令导出变量时,它不是“全局”导出,而只是一个用户本地变量。为什么我会看到它?
2) 最初我有一个猜测:可能是,当我切换到另一个用户时,我启动了我的 bash 进程的一些子进程,这就是为什么我可以看到我的变量,因为导出的变量被传递给当前 shell 的任何子进程。但命令ps ---pid <my bash's pid which I got with echo $$>
在输出中只显示相同的 pid。所以看起来这意味着没有与我的 bash 进程相关的子进程,并且 su 没有启动任何进程。我是对的吗?(顺便说一句,我没有以这种方式看到单个“子进程”,即使我用 bash 命令启动另一个 bash,我也不知道为什么)
3) 最后,谁可以看到我以这种方式导出的变量?假设我从我的 OS GUI 启动了其他进程 - 我会看到它吗?看起来不行,因为如果我启动另一个终端,我在那里看不到它。那么我导出的变量的范围和生命周期是什么?
我使用 Debian Wheezy。我以 Root 用户身份从 RootTerminal 运行命令。
答案1
- 好的,首先,我想你的意思是“
ps --pid
而不是”ps ---pid
。 你不需要
echo $$
输入数字;输入就足够了。除非你谈论的是ps --pid number
ps --pid $$
# echo $$ 42 # su joe % ps --pid 42
在这种情况下,你做的是正确的。
你期待什么?
--pid 进程列表
- 按进程 ID 选择。与以下相同-p和页。
-p 进程列表- 按 PID 选择。这将选择进程 ID 号出现在进程列表。 相同页和--pid。
因此,当您执行 时,您将获得的输出行
ps --pid PID_of_shell
ps
仅适用于 shell 进程。您可能会发现更有用;它将显示包含ps -l | grep PID_of_shell
PID_of_shell
任何地方,包括 PPID 列。即,它将显示 shell 的子进程。但是,当然,grep 42
会找到类似的东西7428
。- 你的猜测是正确的;环境变量从父级传递到子级。如上所述,你的
su
shell 是您的登录 shell(或其他父 shell)的子进程。但请注意,进程可以更改其环境;它sudo
因这样做而臭名昭著,并且su
也会这样做(例如,它会更改$USER
、$LOGNAME
和 ,$HOME
除非您指定--preserve-environment
,如果您指定 ,它会更改得更多--login
)。此外,进程可以向其子进程传递与其正在使用的环境不同的环境;当您说类似 的内容时,shell 会这样做 。参考:PAGER=cat man man_page_topic
1,2。 - 因此,如果您在一个终端的 shell 中设置(导出)环境变量,然后通过窗口管理器启动另一个终端,它将看不到该环境变量,因为它不是设置它的 shell 的子级(或后代)。但是,如果您启动一个新的终端窗口从 shell 中(例如,通过
xterm&
),那么该终端窗口将继承 shell 的环境。
答案2
如果您使用 ssh、rlogin 或 telnet 访问机器,即使以同一用户身份访问,也可能会更容易理解。(不推荐使用 rlogin/telent)
如果您以用户 foo 的身份从 tty1 设置并导出一个变量,则任何子进程都可以看到该变量及其值。但如果您以用户 foo 的身份启动一个全新的会话(即从 tty2 启动),则该变量将不可见。
1) 导出变量时,会将其设为全局变量(在会话上下文中)。顺便提一句,我强烈反对在“root”shell 中工作。当由该用户/帐户执行时,错误和事故就更难以原谅了。
2) su 命令是一个设置(或切换)用户实用程序。您仍处于原始会话中。这就是您仍然可以看到导出的变量的原因。
3) 范围是当前会话,生存期是该会话的持续时间(直到您注销,假设您不再重置或更改变量)。如果您从父会话生成新的 xterm,子会话仍会看到您导出的变量。如果您启动新的会话/终端,则来自其他 tty 的变量及其值不可见。