ループはバックグラウンドサブシェルの変数の変更を無視します。

ループはバックグラウンドサブシェルの変数の変更を無視します。

ループを含むスクリプトを作成しましたuntil。ループは、trueブール変数がループの外側に設定されるまで実行する必要があります。残念ながら、ループは変数がtrueに設定されていることを無視して実行され続けます。この問題を引き起こす行は次のとおりです。

boolean=false
{ sleep 5 && boolean=true && echo "boolean is true now" ; } &
{ until [ "$boolean" = true ] ; do sleep 1 && echo $boolean ; done ; } &&
echo "boolean is true now: $boolean"

生成された出力は次のとおりです。

false
false
false
false
boolean is true now
false
false
false
...

booleanに設定されている場合、ループを終了するにはどうすればよいですかtrue

答え1

信号は、前景シェルと背景シェルとの間の通信に使用することができる。

#!/bin/bash

# global variable for foreground shell
boolean=false

# register a signal handler for SIGUSR1
trap handler USR1

# the handler sets the global variable
handler() { boolean=true; }

echo "before: $boolean"

# Here, "$$" is the pid of the foreground shell
{ sleep 5; kill -USR1 $$; echo "finished background process"; } &

# busy waiting
until $boolean; do 
    echo "waiting..."
    sleep 1
done

echo "after: $boolean"

出力

before: false
waiting...
waiting...
waiting...
waiting...
waiting...
finished background process
after: true

答え2

役割は&バックグラウンドプロセスを実行します。バックグラウンドプロセスはサブシェルで非同期的に実行されます。変数は親シェルから子シェルに渡すことができますが、その逆はできません。ただし、サブシェルに設定された値が本当に必要な場合は、回避策があります。

boolean=$(mktemp) && echo "false" >$boolean
{ sleep 5 && echo true >$boolean && echo "boolean is true now" ; } &
{ until [ "$(cat $boolean)" = "true" ] ; do sleep 1 && cat $boolean ; done ; } &&
echo "boolean is true now: $(cat $boolean)"

これは、内容がブール値である一時ファイルを生成します。untiltrueが含まれるまでループ内のファイルを確認します。

気づく:

(可能であれば)スクリプトで次のことをお勧めします。

{ sleep 5 && echo "background process done" ; } &
wait
echo "continue in foregound."

waitバックグラウンドプロセスが完了するのを待ちます。

答え3

boolean2行目でtrueに設定されたブール値がステートメントでuntilテストされているブール値と同じであると誤って考えます。これは本当ではありません。新しいプロセスを開始し、バックグラウンドで新しいシェルを使用するとboolean(テスト済みのシェル)、割り当てられません。

関連情報