2012-03-11 37 views
4

例として、次のbashスクリプトを考えてみましょう。私が取得したいと思いBash:バックグラウンドでループ内の変数値を取得する方法

AAA 
AAA 
AAA 
... 

出力を::

私が実際に取得

#!/bin/bash 

myvar=AAA 

while true; 
do 
    sleep 3 
    myvar=BBB 
    sleep 3 
    myvar=CCC 
done & 

while true; 
do 
    echo "${myvar}" 
    sleep 1 
done 

出力:2つのループがあり、最初のものは、第1のプリントにmyvar値をバックグラウンドで実行し、

AAA 
BBB 
CCC 
BBB 
CCC 
... 

答えて

7

これは、&が最初のwhileループ用の新しいサブシェルを作成したためです。

私はこれを解決するために何らかの種類のIPCを使用する必要があると確信しています。パイプまたは名前付きパイプを使用してプロデューサ/コンシューマの設定を実装するのは合理的です。

ラフ例:

#!/bin/bash 

myvar=AAA 

while true; 
do 
    sleep 3 
    myvar_piped=BBB 
    echo $myvar_piped # this goes to the pipe. 
    sleep 1 
done | # this connects the two loops. 

while true; 
do 
    # if we consumed something (timeout=1) print it, else print our own variable. 
    if read -t 1 myvar_piped # 
    then 
     echo "${myvar_piped}" 
    else 
     echo "${myvar}" 
    fi 
done 

出力:実質

AAA 
AAA 
AAA 
BBB 
AAA 
AAA 
AAA 
AAA 
BBB 
+0

ありがとうございました。私はbashの初心者です、あなたは私に例を教えてもらえますか? – mt22

+0

+1例では、最初のループはもうバックグラウンドで実行されません.2つのループは順番に実行されますが、そうではありませんか? – mt22

+0

@Lorenzo:いいえ、パイプは最初のループを2番目のループに接続し、両方がパラレルで実行され、入力などの待機を行うことができる同期はできません。それをコマンドラインで構築することができる他のパイプと考えてください。ただし、コマンドの代わりにwhileループを使用してください。 –

4

、あなたは親シェルに直接変数を読み取ることができることは何もありません。

&のため、最初のループはサブシェルで実行されます。サブシェルのメモリはメインシェルのメモリとは完全に独立しており、親シェルから子のメモリにアクセスする方法はありません(サブクラスでデバッガを実行するなどの厄介なことはありません)。

サブシェルプロセスを変更して毎秒変数の値を書き込むことができれば、親がそれを検出できる可能性があります。サブシェルは、変数を変更するたびに、あなたはできるだけ頻繁にあなたが親に好きなファイルを読むことができます知られている名前のファイルに変数を書き込むとまた、:

#!/bin/bash 

tmp=$(mktemp) 

trap "rm -f $tmp; exit 1" 0 1 2 3 13 15 

myvar=AAA 
echo $myvar > $tmp 

while true; 
do 
    sleep 3 
    myvar=BBB 
    echo $myvar > $tmp 
    sleep 3 
    myvar=CCC 
    echo $myvar > $tmp 
done & 

while cat $tmp 
do 
    sleep 1 
done 

rm -f $tmp 
trap 0 

trapperyは確実に一時ファイルはほとんどの状況(HUP、INT、QUIT、PIPE、TERMシグナル)で削除されます。

+0

ありがとうございます。より強力なスクリプト言語が私のニーズをより良く満たすと思いますか? – mt22

+1

どのようなスクリプト言語でも共有メモリを設定しなければ、PerlとPythonがその仕事をすることができるとは思っても、まったく魅力的ではありません。共有メモリーに書き込んだり読み込んだりする必要があるので、変数を共有メモリーに配置する必要があります。私はファイルベースのIPCシステムのいくつかの並べ替えがあなたのために良いかもしれないと思う。より強力なスクリプト言語を使用すると、毎秒ファイルを再オープンするのではなく、親ファイルを開いたままにして巻き戻して再読込できるようになります。 OTOH、あなたがループで「スリープ1」を持っているとき、パフォーマンスはそれほど重要ではありません。 –

+0

+1。あなたの解決策も良いです。 – mt22

関連する問題