2016-09-05 44 views
1

私はbashを学んでいます。私の現在の理解では、サブシェルで使用するために関数をエクスポートする必要があります。しかし、私はサブシェルでエクスポートされていない関数を呼び出すことができます。なぜ、どのようにエクスポートされていない関数がサブシェルで動作するかを知りたい。テストコードは、以下の通りですなぜサブシェルでエクスポートされていない関数を呼び出すことができますか?

ファイル名:level1.sh

#!/bin/bash 
function level_1_func { 
    echo "function 1: $1, PID=${BASHPID}" 
} 

ファイル名:「はbashの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}" 

出力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 

答えて

1

これは、関数の場合だけでなく、環境内の他のもの(シェルオプション、ローカル変数など)でもあります。例えば

3.2: ~$ set -o nounset 
3.2: ~$ echo $(set -o|grep nounset) 
nounset on 
3.2: ~$ bash -c 'set -o|grep nounset' 
nounset   off 

用語 "サブシェル" 酷使、しばしば不正確である:

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: ~$        

ここシェル・オプションを使用した例です。 "真の"サブシェルを作成すると、bashは現在のプロセスのコピーを作成します。したがって、すべてがコピーされます(forkアクション)。新しいプロセスを作成すると、基本的に環境ブロック内にないもの、つまりエクスポートされたもの(他のものも、ユーザーやグループID、現在のディレクトリなどの元のプロセスから保持されます)が破棄されます(execタイプアクション)。 )。

+1

ありがとうございます。私は、あなたが言うように、2つのタイプのサブシェル、フォークタイプ、およびexecタイプを区別する方が良いということに同意します。彼らははるかに明確です。 – mora

+0

私はサブシェルが 'fork'アクションだと言います。 'fork/exec'アクションは、別のプロセスを独自のプログラムで実行しているだけです。これは子プロセスですが、シェルではない可能性があります。 – cdarke

4

サブシェルはコマンド置換によって呼び出されましたが、このサブシェルは現在のシェルと同じコンテキストを持っています。新しいコンテキストを作成するには、明示的にbashを呼び出す必要があります。

out_puts="$(bash -c level0_func level0_func "in the sub shell")" 
+0

ありがとうございます。私はbashマニュアルで "文脈"の指示を見つけようとしました。しかし、私はそれを見つけることができませんでした。私がどこでそれを教えることができるか教えてください。 – mora

+0

私はその名前の正式な構成はないと思います。単にbashプロセスのすべての内部構造を参照するだけです。 –

+0

もう一度ありがとうございます。私はbashマニュアルで文を見つけました: "関数をエクスポートして、サブシェルが自動的にエクスポート組み込み関数に-fオプションで定義されるようにすることができます。私は、文中のサブシェルは、あなたの例では明示的に生成されたシェルを意味しますが、コマンド置換によって生成されるシェルではないと考えます。サブシェルに関数をエクスポートする必要があるのは唯一のケースですか? – mora

関連する問題