2016-04-04 23 views
1

私は1つのスクリプトから変数をエクスポートして、別のスクリプトでそれを使用しようとしていますが、この変数は共有変数

がSCRIPT1

#!/bin/sh 
export x=19 
exit 0 
としてこれを考慮して、問題が何であるか、エクスポートされていません

私は

のような二つの独立したスクリプトとしてそれらを実行していますスクリプト2

#!/bin/sh 
echo "x="${x} 
exit 0 

としてこれを考えてみましょう

desktop:~/Desktop/Trail_Programs$ sh script1.sh 
desktop:~/Desktop/Trail_Programs$ sh script2.sh 

出力script2.shから

desktop:~/Desktop/Trail_Programs$ sh script2.sh 
x= 
+1

スタックオーバーフロー['bash'タグwiki](http://stackoverflow.com/tags/bash/info)のよくある質問の中で、http://stackoverflow.com/questions/17852111/unable-スクリプトファイルをエクスポートする変数とスクリプトファイルをエクスポートするhttp://stackoverflow.com/questions/4277665/how-do-i-compare-two-string-variables-in-an-if-statement-in- bash - これらはどちらもよくある質問です。 – tripleee

+0

ありがとう@tripleee –

答えて

1

David C. Rankin's helpful answerなぜあなたのコードうまくいかなかった。

注:あなたがで動作するスクリプトを修正することはできない場合は
次ソリューションは、(あなたがソーシングとアドホック環境変数について知りたい場合は解決策にも興味があります)を使用する必要があります。
それ以外の場合は、下部に記載されている解決策を参照してください。

あなたの問題を解決するには、次のように試すことができます。

x=$(trap 'printf %s "$x"' EXIT; . script1.sh >/dev/null) sh script2.sh 

ただし、:

  • script1.shがします - 必然的に - あなたの現在のシェルによって実行されますこれはshである場合とそうでない場合があります。
  • script1.shの出力は抑制されます。printf %s "$x"がコマンド置換($(...))内のサブシェルによって生成される唯一のstdout出力であることが保証されなければならないからです。
  • このアプローチは単一の変数に制限されています(ただし、呼び出し元のスクリプトが個別の値に解析しなければならない複数の変数の値を出力するように拡張することもできます)。

. script1.shサブシェルは、独自の環境で直接script1.shを実行することを意味し、したがって、それがなかった場合でも、それは$xを見ることを意味している(それを実行した後、スクリプトの変数を見てサブシェル内のスクリプト、 をエクスポート)。

trap 'printf %s "$x"' EXITは終了トラップを設定します。すなわち、サブシェルが終了するときに実行されるコード、この場合はprintf %s "$x"であり、単に関心のある変数の値を出力する。
ステートメントのためにscript1.shが終了しても、$xの値が確実に出力されるようにするには、この方法が必要です。 script1.shのサブシェルであるであるため、exitはサブシェル全体を終了します。

x=$(...)は、その値を取り込み、そして、sh script2.shを指令するを前に付加されることによって、効果的にscript2.shが、その後見ている結果$x環境変数になります。


これは、一般的に調達するように設計されていないソースのスクリプトに問題です:

  • すべてスクリプトによって変更または作成された変数と行っシェル環境に変更スクリプトが呼び出すシェルに影響します。
  • このようなスクリプトでexitが実行されると、呼び出し元のシェルも終了します。

何らかの理由でスクリプトを変更できない場合、いくつかの制限がありますが、これらの問題を回避するため、上記の解決方法が最適です。


より強固な、一般的なソリューション(必要なスクリプトの変更):

関心自体の環境変数(複数可)を設定するスクリプトを持つ他のスクリプトが適切なソリューションである呼び出しますDavid's answerに示すように、

スクリプトがピアとして実行する必要がある場合は、値がファイルを経由して渡される必要があります。興味のある変数を設定するスクリプト(s)は(一時的な)ファイルにその値を書き込み、他のを持っています

script1.sh

#!/bin/sh 
export x=19 
# Write to temp. file named for the *parent* process ID. 
# Since both script calls will have the same parent process, this 
# allows you to avoid a static filename subject to name collisions. 
printf %s "$x" > /tmp/x.$PPID 

script2.sh

#!/bin/sh 
# Read the value of $x from the temp. file, then delete the file. 
x=$(cat /tmp/x.$PPID) && rm /tmp/x.$PPID 
echo "x=${x}" 
スクリプトは、そのファイルを読みます
2

sourcescript1.shです。行(shebang後)script2.shの開始時に

、追加:

source /path/to/script1.sh 
+0

これはいくつかのケースではうまくいくかもしれませんが、一般的に、ソースとなるように設計されていないソーススクリプトには問題があります。 呼び出すシェルの環境を汚染する可能性を除いて、より大きな懸念事項は、ソーススクリプト (OPのサンプルスクリプトに示されている)の 'exit'ステートメントです。これは必然的に呼び出しシェルを直ちに終了させるからです。いずれにせよ、第一の直感は、最も類似したケースで第二のスクリプトを 'ソース化する 'ことです。 – mklement0

+0

@ mklement0 duh。 './script2.sh'は_subshel​​l_を作成しません。それは_childプロセスを作成します。このプロセスはshell_です。エクスポートされた変数は、シェルであろうとなかろうと、子プロセスから見える環境変数になります。また、私は "_cannot_は親の環境に影響を与える"と言っています。 – heemayl

0

では、次の内容

#this file tobeincluded1 will be included in master 
x=16 

でファイルtobeincluded1を持っており、以下の内容

#this file tobeincluded2 will be included in master 
y=21 
tobeincluded2ファイルとし

あなたは上記のファイルをあなたの以下のような.またはsourceのいずれかを使用してCRIPT:

#!/bin/bash 

. ./tobeincluded1 #using the . to include a file 
source ./tobeincluded2 #using the source command to include a file 

echo "x : $x" 
echo "y : $y" 
2

は、スクリプトがは、その親の環境に影響を与えないかもしれない覚えておいてください。 は、NEVERを意味し、は、NEVERを意味する。だから、ルールを次

#!/bin/bash 
export x=19 
exit 0 

は、環境上のNO効果を持っており、そこx=anythingを設定しません。 exportは、そのスクリプト内から作成されたサブシェルの環境にのみ影響します。たとえば、スクリプトを取る、exp.shそれを呼び出す:

#!/bin/bash 
export x=19 
./script2.sh 
exit 0 

script2.shにあなたが持っている:そして、

echo "x = $x" 

を、とだけにして、あなたが得る:

だけだ
$ bash exp.sh 
x = 19 

をルール...

+1

++; – mklement0

+0

私はこれらの2つのスクリプトを独立して実行しなければならないと仮定し、2つのスクリプトの間に親子関係は存在しません。 –

+0

ルールに違反しています。あなたの環境で何かを設定する必要があるとき。あなたは '/ etc/profile'や'/etc/bashrc'や '$ HOME'のバージョン(例えば'〜/ .bashrc')に限られています。これがLinuxシェルが動作する方法です。変数を含むコードを現在のシェル/スクリプトに 'ソース化 'することはできますが、親には影響しません。 'PS1'と' PATH'がどこにどのように設定されているのか考えてみてください。これがまさにその理由だ。あなたはいつも 'tmp'ファイルを書いて' script2'から読み込むことができます。環境を使うことはできません。 –

関連する問題