Sto*_*row 11 bash shell subprocess subshell
我对bash变量是否导出到子shell以及何时可以通过脚本访问感到困惑.到目前为止,我的经验使我相信bash变量可自动用于子shell.例如:
> FOO=bar
> echo $FOO
bar
> (echo $FOO)
bar
Run Code Online (Sandbox Code Playgroud)
以上似乎表明bash变量可以在子壳中访问.
鉴于此脚本:
#! /usr/bin/bash
# c.sh
func()
{
echo before
echo ${FOO}
echo after
}
func
Run Code Online (Sandbox Code Playgroud)
我知道在当前shell上下文中调用脚本可以访问当前shell的变量:
> . ./c.sh
before
bar
after
Run Code Online (Sandbox Code Playgroud)
如果我在没有"点空间"先例的情况下调用脚本...
> ./c.sh
before
after
Run Code Online (Sandbox Code Playgroud)
...是不是在子shell中调用脚本的情况?如果是这样,并且当前shell的变量可用于子shell(正如我从最初的代码块推断的那样)也是$FOO如此,为什么c.sh在以这种方式运行时不可用?
类似地,为什么在括号内运行$FOO时也不可用c.sh- 我理解为在子shell中运行表达式:
> (./c.sh)
before
after
Run Code Online (Sandbox Code Playgroud)
(如果这个问题没有太多问题:如果" ./c.sh"和" (./c.sh)"都在当前shell的子shell中运行脚本,那么两种调用方式之间有什么区别?)
(...)...在一个单独的环境中运行,最容易实现(并在bash,dash和大多数其他POSIX-y shell中实现)使用子shell - 也就是说,通过fork()旧shell 创建的子项,但不调用任何子execv shell -家庭功能.因此,父项的整个内存中状态是重复的,包括未导出的shell变量.
./other-script相反,它other-script作为一个完全独立的可执行文件运行; 它并没有在子shell后保留非出口变量(这是不是一个子shell!)已被调用.其工作原理如下:
fork()创建一个孩子.此时,孩子仍然有甚至未导出的变量状态被复制../other-script >>log.out,孩子会open("log.out", O_APPEND),然后fdup()描述符1覆盖,覆盖stdout).execv("./other-script", {"./other-script", NULL}),指示操作系统用新的实例替换它other-script.在此调用成功之后,在子PID下运行的进程是一个全新的程序,只有exported变量才能生存.