为什么我可以调用未在子shell中导出的函数?

时间:2016-09-05 03:52:15

标签: bash

我正在学习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

2 个答案:

答案 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,当前目录等。)。