循环忽略后台子 shell 中变量的更改

循环忽略后台子 shell 中变量的更改

我编写了一个包含循环的脚本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

可以使用信号在前台 shell 和后台 shell 之间进行通信:

#!/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

角色&进行后台进程。后台进程在子 shell 中异步执行。变量可以从父 shell 传递到子 shell,而不是相反。但是,如果您确实需要子 shell 中设置的值,则可以采取解决方法:

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)"

这会生成一个临时文件,其内容是布尔值。在until循环中检查该文件直到它包含 true。

注意:

我建议在您的脚本中执行以下操作(如果可能):

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

wait等待后台进程完成。

答案3

您错误地认为boolean在第二行中设置为 true 的布尔值与您在until语句中测试的布尔值相同。情况并非如此,您启动新进程,在后台使用一个新的 shell,并且boolean(您测试的那个)永远不会被分配。

相关内容