这是一个重现我的问题的脚本。该函数回显并更改变量。无论我先按下一个键还是让计时器先用完都没关系,两次调用的变量都不会改变,它只是打印“Not touched!”两次,这对我来说很奇怪。
#!/bin/bash
func(){
echo "$globalVar"
globalVar="touched!"
}
globalVar="Not touched!"
trap func EXIT
(sleep 3 && func) &
read -n1 -r -p "Press any key to exit..."
我希望它回显“未触及!”第一次和“感动!”第二次。
编辑: 与使用后台进程的 (sleep 3 && func) $ 行有关。那么我的问题是如何使变量真正成为全局变量?
内置的
trap
由 posix sh
指定,bash 受该规范约束。来自官方规范:
shell 在 EXIT 上执行陷阱的环境应与在执行 EXIT 陷阱之前执行的最后一个命令之后立即相同的环境。
每次调用 trap 时,动作参数的处理方式等同于:
eval action
这应该可以回答您标题中的问题。但是,您的脚本受到另一个可能有点混乱的其他细节的影响:
在子流程中,您不能更改父流程的变量。如果你有像 ...
这样的命令,这可能看起来很明显#! /bin/bash
x=1
bash -c 'x=2'
echo "$x"
...但是 bash 在很多地方启动所谓的子 shell,例如在管道 (
subshell1 | subshell2
)、替换 command "$(subshell)"
、后台进程 subshell &
和显式子 shell (subshell)
.
(sleep 3 && func) &
在子 shell 中运行,因此不能改变父进程的全局变量。
我的问题是如何使变量真正成为全局变量?
如果你想在两个进程之间共享一个变量,那么使用内置函数是不可能的。您需要某种方式来进行进程间通信。在 shell 中,最简单的解决方案是读取和写入文件/fifos。细节取决于你到底想达到什么目的。