2016-09-19 15 views
1

Bashでは、コマンドteeが実行された後、一部のグローバル変数が予期せずアンセットされます。予期しない環境変数unset

テストコードは、次のように

#!/bin/bash 
function set_global_variable(){ 
     GLOBAL_VARIABLE="global_variable" 
     echo "set GLOBAL_VARIABLE($GLOBAL_VARIABLE)" 
} 

function get_global_variable(){ 
     echo "get GLOBAL_VARIABLE($GLOBAL_VARIABLE)" 
} 

function normal_test(){ 
     unset GLOBAL_VARIABLE 
     set_global_variable 
     get_global_variable 
} 

function unnormal_test(){ 
     unset GLOBAL_VARIABLE 
     set_global_variable |tee random_file 
     get_global_variable 
} 

echo "normal_test" 
normal_test 

echo "unnormal_test" 
unnormal_test 

結果:

normal_test 
set GLOBAL_VARIABLE(global_variable) 
get GLOBAL_VARIABLE(global_variable) 
unnormal_test 
set GLOBAL_VARIABLE(global_variable) 
get GLOBAL_VARIABLE() 

unnormal_testにおけるGLOBAL_VARIABLEの値がヌルである、なぜですか?

+0

パイプでは、コマンドはサブシェルで実行されます。つまり、環境に対する変更はすべて親シェルでは表示されません。 – Leon

答えて

1

問題は、この行を次のとおりです。

set_global_variable |tee random_file 

この行が実行されると、bashは、パイプラインの各コンポーネントのサブシェルを作成し、そこにそれらを実行します。したがって、set_global_variableは実際に変数を設定しますが、別のプロセスでそれを行います。次の行にget_global_variableを実行すると、これによって影響を受けていない元のプロセスに残ります。

ここではその効果の単純な例です:

true | a=1 
echo $a 

これは、上記で説明したのと同じ理由のために何も印刷されません。一方:echo $aa=1と同じサブシェルから実行されるため、

true | { a=1; echo $a; } 

は、1を出力します。最後の例はあまり実用的ではありません。

したがって、一般的なルールでは、サブシェルに変数を設定しないでください。