bash变量什么时候导出到子shell和/或可由脚本访问? [英] When are bash variables exported to subshells and/or accessible by scripts?

查看:103
本文介绍了bash变量什么时候导出到子shell和/或可由脚本访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于bash变量是否导出到子shell以及何时可以通过脚本访问它们,我感到困惑.到目前为止,我的经验使我相信bash变量可自动用于子shell.例如:

I'm confused over whether bash variables are exported to subshells and when they are accessible by scripts. My experience so far led me to believe that bash variables are automatically available to subshells. E.g.:

> FOO=bar
> echo $FOO
bar
> (echo $FOO)
bar

上面的内容似乎表明bash变量可在子shell中访问.

The above appears to demonstrate that bash variables are accessible in subshells.

给出此脚本:

#! /usr/bin/bash
# c.sh

func()
{
  echo before
  echo ${FOO}
  echo after
}

func

我了解在当前shell上下文中调用脚本可以使它访问当前shell的变量:

I understand that calling the script in the current shell context gives it access to the current shell's variables:

> . ./c.sh 
before
bar
after

如果我在没有点空格"先例的情况下调用脚本...

If I were to call the script without the "dot space" precedent...

> ./c.sh 
before

after

...不是在子shell中调用脚本的情况吗?如果是这样的话,那么当前shell的变量也可用于子shell(正如我从第一个代码块推断的那样),为什么$FOO对于这种方式运行时对c.sh不可用?

...isn't it the case that the script is called in a subshell? If so, and it's also true that the current shell's variables are available to subshells (as I inferred from the firstmost code-block), why is $FOO not available to c.sh when run this way?

类似地,当c.sh在括号内运行时,为什么$FOO也不可用-我理解这意味着在子shell中运行该表达式:

Similarly, why is $FOO also unavailable when c.sh is run within parentheses - which I understood to mean running the expression in a subshell:

> (./c.sh)
before

after

(如果这不使本文含太多问题,如果"./c.sh"和"(./c.sh)"都在当前shell的子shell中运行脚本,则两种调用方式之间有什么区别?)

(If this doesn't muddy this post with too many questions: if "./c.sh" and "(./c.sh)" both run the script in a subshell of the current shell, what's the difference between the two ways of calling?)

推荐答案

(...)在单独的环境中运行...,使用以下方法最容易实现(并在bash,dash和大多数其他POSIX-y shell中实现)子外壳程序-也就是说,是通过fork()修改旧外壳程序而创建的子程序,但不调用任何execv -family函数.因此,将复制父对象的整个内存状态,包括未导出的shell变量.

(...) runs ... in a separate environment, something most easily achieved (and implemented in bash, dash, and most other POSIX-y shells) using a subshell -- which is to say, a child created by fork()ing the old shell, but not calling any execv-family function. Thus, the entire in-memory state of the parent is duplicated, including non-exported shell variables.

./other-script作为完全独立的可执行文件运行other-script.在调用子外壳程序(不是子外壳程序!)之后,它 not 不会保留未导出的变量.其工作原理如下:

./other-script, by contrast, runs other-script as a completely separate executable; it does not retain non-exported variables after the child shell (which is not a subshell!) has been invoked. This works as follows:

  • shell调用fork()创建一个子代.此时,该子项甚至还复制了未导出的变量状态.
  • 该子节点接受任何重定向(如果它是./other-script >>log.out,则该子节点将open("log.out", O_APPEND)然后将fdup()描述符转移到1,覆盖标准输出).
  • 该子代调用execv("./other-script", {"./other-script", NULL})指示操作系统将其替换为新的other-script 实例.调用成功后,在孩子的PID下运行的进程是一个全新的程序,只有export ed变量可以保留.
  • The shell calls fork() to create a child. At this point in time, the child still has even non-exported variable state copied.
  • The child honors any redirections (if it was ./other-script >>log.out, the child would open("log.out", O_APPEND) and then fdup() the descriptor over to 1, overwriting stdout).
  • The child calls execv("./other-script", {"./other-script", NULL}), instructing the operating system to replace it with a new instance of other-script. After this call succeeds, the process running under the child's PID is an entirely new program, and only exported variables survive.

这篇关于bash变量什么时候导出到子shell和/或可由脚本访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆