Unix shell 变量中“exported”的范围是什么?

Unix shell 变量中“exported”的范围是什么?

我已经按照以下方式设置了一些环境变量:

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 numberps --pid $$

    # echo $$
    42
    # su joe
    % ps --pid 42
    

    在这种情况下,你做的是正确的。

  • 你期待什么?

    --pid 进程列表

      按进程 ID 选择。与以下相同-p


    -p 进程列表

      按 PID 选择。这将选择进程 ID 号出现在进程列表。 相同--pid

    因此,当您执行 时,您将获得的输出行ps --pid PID_of_shellps仅适用于 shell 进程。您可能会发现更有用;它将显示包含ps -l | grep PID_of_shellPID_of_shell任何地方,包括 PPID 列。即,它将显示 shell 的子进程。但是,当然,grep 42会找到类似的东西7428

  • 你的猜测是正确的;环境变量从父级传递到子级。如上所述,你的sushell 是您的登录 shell(或其他父 shell)的子进程。但请注意,进程可以更改其环境;它 sudo因这样做而臭名昭著,并且 su也会这样做(例如,它会更改$USER$LOGNAME和 ,$HOME 除非您指定--preserve-environment,如果您指定 ,它会更改得更多--login)。此外,进程可以向其子进程传递与其正在使用的环境不同的环境;当您说类似 的内容时,shell 会这样做 。参考:PAGER=cat man man_page_topic12
  • 因此,如果您在一个终端的 shell 中设置(导出)环境变量,然后通过窗口管理器启动另一个终端,它将看不到该环境变量,因为它不是设置它的 shell 的子级(或后代)。但是,如果您启动一个新的终端窗口从 shell 中(例如,通过xterm&),那么该终端窗口将继承 shell 的环境。

答案2

如果您使用 ssh、rlogin 或 telnet 访问机器,即使以同一用户身份访问,也可能会更容易理解。(不推荐使用 rlogin/telent)

如果您以用户 foo 的身份从 tty1 设置并导出一个变量,则任何子进程都可以看到该变量及其值。但如果您以用户 foo 的身份启动一个全新的会话(即从 tty2 启动),则该变量将不可见。

1) 导出变量时,会将其设为全局变量(在会话上下文中)。顺便提一句,我强烈反对在“root”shell 中工作。当由该用户/帐户执行时,错误和事故就更难以原谅了。

2) su 命令是一个设置(或切换)用户实用程序。您仍处于原始会话中。这就是您仍然可以看到导出的变量的原因。

3) 范围是当前会话,生存期是该会话的持续时间(直到您注销,假设您不再重置或更改变量)。如果您从父会话生成新的 xterm,子会话仍会看到您导出的变量。如果您启动新的会话/终端,则来自其他 tty 的变量及其值不可见。

相关内容