[英]Assign variable in the background shell
我想要在显示这样的进度指示器时在后台分配变量
sleep_echo(){
sleep $1
echo $2
}
show_ellapsed_time () {
#...
}
(mivar=$(sleep_echo 3 hello)) &
show_ellapsed_time $!
echo $mivar
echo "after asignment"
当我在终端中运行它时,它会输出进度指示器,然后myvar
processing 00:00:03 [\]
hello
after asignment
但是,当我在脚本中运行分配时,分配不会发生
processing 00:00:03 [\]
after asignment
为什么会失败? 函数不被调用吗?
子进程无法通过变量分配与其父进程进行通信。
在Bash中,可以通过几种方式创建子进程:
()
括起来的语句启动子外壳 &
在后台启动任何东西 外部命令会收到所有标记为导出的shell变量的副本(例如export VAR
, local -x VAR
)
子shell接收所有变量的副本。 这很有用,但是很容易就不会意识到自己处在新的环境中。 在子进程中所做的任何分配都不会被父进程看到。
你可以做什么:
mkfifo
)。 对于最后一个,使用<(COMMAND)
和>(COMMAND)
类的进程替换通常比使用|
构建的典型管道要好得多|
,例如,允许while
循环的主体(或实际上是向/从中馈入替代的任何其他语句)保留在脚本的上下文中。 这允许循环内的变量分配具有预期的效果。
就您而言,您有以下几行:
(mivar=$(sleep_echo 3 hello)) &
show_ellapsed_time $!
也许您可以将它们替换为:
show_ellapsed_time &
BG_PID=$!
mivar=$(sleep_echo 3 hello)
kill $BG_PID
我对您的show_ellapsed_time
了解,如果没有传递给该函数的参数,那是否可以正常工作,但是分配可以工作。 您还可以将主外壳的PID传递给函数,如下所示:
show_ellapsed_time $$ &
您的变量在另一个作用域内。 如果将某些命令用圆括号(
和)
括起来,则在该范围外使用的变量将不再可访问。 一个例子:
(myvar=test)
echo "myvar=$myvar"
会给:
myvar=
因为不再知道myvar。 您的命令似乎在终端中起作用的唯一原因是: 可能是您在测试期间设置了变量mivar
; 因此该变量仍处于设置状态。 如果您打开一个新终端,您的脚本将不再起作用。
将流程发送到后台(使用&
); 也将导致范围发生变化; 因此即使卸下支架也无济于事。 我认为您应该重新设计脚本(或考虑使用高级语言),因为似乎您想将多线程引入bash :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.