我正在学习bash。在我目前的理解中,我需要导出函数以在子shell中使用它。但是,我可以调用一个不在子shell中导出的函数。我想知道非导出函数为什么或如何在子shell中工作。测试代码如下,
文件名:level1.sh
#!/bin/bash
function level_1_func {
echo "function 1: $1, PID=${BASHPID}"
}
文件名:level0.sh
#!/bin/bash
# *** If you don't load level1.sh before this function or script,
# *** level_1_func in this function causes an error of "command not found"
function level0_func {
echo "function 0: $1, PID=${BASHPID}"
level_1_func "inside level0_func"
}
top.sh
source "./level0.sh"
# *** Error in level0_func : "level_1_func: command not found."
# *** It is because level1.sh has not been loaded.
level0_func "in the current shell"
# *** Here it loads level1.sh. After this lines,
# *** it can call level_1_func even in sub-shell.
# *** (definition of function is exported automatically?)
source "./level1.sh"
out_puts="$(level0_func "in the sub shell")"
echo "${out_puts}"
输出" bash top.sh"正在关注
function 0: in the current shell, PID=7575
./level0.sh: line 7: level_1_func: command not found
function 0: in the sub shell, PID=7577
function 1: inside level0_func, PID=7577
答案 0 :(得分:4)
命令替换调用了一个子shell,但是这个子shell与当前shell具有相同的上下文。您需要显式调用bash
以创建新上下文。
out_puts="$(bash -c level0_func level0_func "in the sub shell")"
答案 1 :(得分:1)
这不仅仅是函数的情况,而是环境中的其他所有内容,包括shell选项,甚至是局部变量。
例如:
3.2: ~$ foo=42
3.2: ~$ set|grep foo
foo=42
3.2: ~$ echo $(set|grep foo)
foo=42
3.2: ~$ bash -c set|grep foo
3.2: ~$
以下是使用shell选项的示例:
3.2: ~$ set -o nounset
3.2: ~$ echo $(set -o|grep nounset)
nounset on
3.2: ~$ bash -c 'set -o|grep nounset'
nounset off
术语“子壳”过度使用,通常不准确。当您创建“true”子shell时,bash会复制当前进程,因此所有都将被复制(fork
操作)。当您创建一个新进程时,它基本上会破坏(exec
类型操作)任何不在环境块中的内容,即导出的内容(其他内容也会保留在原始进程中,例如用户和组ID,当前目录等。)。