bash v3.2 (虽然我认为更新版本也适用):
在第3.7.4节“环境”中,文件指出:
在调用时,shell扫描它自己的环境,并为找到的每个名称创建一个参数,并自动标记它以导出到子进程。
在附录B中,与Bourne Shell的主要区别是:
shell初始环境中的变量将自动导出到子进程。Bourne通常不会这样做,除非使用export命令显式地标记变量。
我不明白这意味着什么。
在以下内容中,cmd1.sh包括
#!/bin/bash
echo yes $ben from cmd1
./cmd2.sh而cmd2.sh包括
#!/bin/bash
echo yes $ben from cmd2我首先将docs理解为所有分配的变量都将被导出(即不需要export变量),即在运行时
ben=you;
./cmd1.sh我以为这个会印出来
yes you from cmd1
yes you from cmd2但它却打印了
yes from cmd1
yes from cmd2因此,变量ben似乎不会自动导出。然后,我认为文档可能反而意味着所有的环境变量都将被导出(即在运行时)。
ben=you;
export ben;
./cmd1.sh因为cmd1接收到ben的环境变量,所以ben将自动导出,以便在cmd2中可见。我预计这将打印以下内容(实际上是打印如下):
yes you from cmd1
yes you from cmd2但是,为了测试这与Bourne (如docs声称的那样)是否不同,我运行了完全相同的命令,但是将shebang更改为指向/bin/sh而不是/bin/bash,得到了完全相同的结果。我看不出有什么不同。在Bourne shell中,我希望看到这样的输出
yes you from cmd1
yes from cmd2有人能帮助我理解文档在谈论导出的“自动”标记参数时所指的是什么吗?这与Bourne有何不同?
注:我确实注意到了这关于bash和bourne中export行为之间的一个具体区别的问题,但这似乎并不相关。
发布于 2023-03-28 08:55:46
“shell初始环境中的变量将自动导出到子进程。Bourne通常不会这样做,除非使用export命令显式地标记变量。”
考虑:
% export FOO=abc
% bash -c 'FOO=xyz; echo "bash: FOO=$FOO"; echo "env:"; env |grep FOO'
bash: FOO=xyz
env:
FOO=xyz在这里,我已经在我的交互式shell中设置了FOO (zsh,但这并不重要),并将它设置为导出。然后运行Bash,它在其环境中接收该变量,更改它的值,打印它,然后运行env。这是一个外部命令,因此它只看到内部Bash显式传递给它的变量。我们看到FOO的修改后的值在内部Bash和env中都是可见的,因此Bash确实从它的环境中导入了变量,并将其作为传递导出变量的方式传递给它。
引用似乎描述的另一种行为是,内部外壳不会将变量传递给env,相反,您会看到这样的情况:
bash: FOO=xyz
env:我不知道所有历史实现的实际行为是什么,我所能再现的只有传家宝-sh(与Kusalananda提到的行为相同),只传递变量的原始值:
% ./heirloom-sh -c 'FOO=xyz; echo "sh: FOO=$FOO"; echo "env:"; env |grep FOO'
sh: FOO=xyz
env:
FOO=abc显式的export FOO内部shell也会传递当前值。在这里,FOO的原始值在脚本中是可见的,所以echo "FOO=$FOO"作为第一件事也会打印FOO=abc。
发布于 2023-03-28 08:27:03
您不使用原始的Bourne,因此您不会期望看到Bourne行为。POSIX sh shell (由bash或dash或在您的系统上以POSIX模式运行的其他shell实现)和bash的行为相同,并且在环境变量方面没有伯恩shell行为。
在POSIX中(如sh、bash、dash和Unix上的大多数其他常见shell ),shell从shell的父进程继承的环境变量将传递给shell启动的任何子进程。附录中的文本将此称为“自动导出到子进程”的环境变量。
附录声称,在原始Bourne中不是这种情况,由子进程继承的环境变量必须使用export命令显式导出,无论它们是由shell从父环境继承还是在shell中创建。
我所知道的最接近于最初的Bourne的shell是/usr/sunos/bin/sh论Solaris。从代码库的角度来看,这是真正的原始Bourne,但它可能在过去几年中进行了一些更新。
根据它的手册,这个shell的行为并不像bash文档的附录所描述的那样。它确实将继承的环境变量传递给其子进程。但是,如果要修改继承的环境变量,则必须将它们导出为子进程,以查看更改的值:
在调用时,shell扫描环境,并为找到的每个名称创建一个参数,给出相应的值。If用户修改这些参数的值或创建新的参数,这些参数都不会影响环境,除非
exportcommand用于将shell的参数绑定到环境(另请参阅set –a)。可以使用unset命令从环境中删除一个参数。因此,任何执行命令所看到的环境都由任何未经修改的名称-值对组成,它们最初由shell继承,减去由unset、plus删除的任何修改或添加,所有这些都必须在export命令中注明。
发布于 2023-03-28 10:18:14
未导出的变量不在子进程的环境中。这意味着当您运行子shell时,它们不在该shell的初始环境中。
“shell初始环境中的变量自动导出到子进程”是正确的,但是如果这些变量还没有在环境中,那么这些变量将无法用于该shell或重新导出到子shell的子进程。
这就是未导出的shell变量和导出的环境变量之间的区别。shell变量是当前Shell的本地变量,导出的变量对于当前shell (或其他程序)及其子程序是可见的。
还值得注意的是:子进程不能更改其parent...so的环境,更改子进程中的env对父进程没有任何影响。
https://unix.stackexchange.com/questions/741170
复制相似问题