在 shell 脚本中停止异步 while 循环

在 shell 脚本中停止异步 while 循环

我有一个异步 while 循环,可以重新启动进程,直到满足某些条件。这看起来像这样:

(while [ "$check_condition" -eq 1 ]; do
    ./async_command
done) &

... # do some stuff

check_condition=0
pkill -9 async_command

如您所见,我更改check_condition为 0 并终止仍在运行的异步进程。问题是, while 循环仍然会触发并且进程会重新启动。

我猜测循环仅注册check_condition启动后的值,并且不会注意到任何变化。

我怎样才能解决这个问题?

答案1

您需要kill $!终止后台运行的最后一个进程。看在 Bash 脚本中,“$!”是什么意思?

如果您在后台运行其他命令,您可以将其 PID 保存在变量中$!,稍后使用该 Id 在您需要的任何地方终止该进程。

( while ... done ) & pid=$!

然后

kill $pid

或用于jobs确定正在运行的后台进程并使用其 ID 杀死它。

kill %Id

也可以看看如何终止后台进程?

答案2

coproc用于模拟命名循环

最接近命名循环bash的可能是coproc

coproc loop1 { while ((1)) ; do echo a >> aout ; sleep 1 ; done ;} 
echo PID of loop1 $loop1_PID
coproc loop2 { while ((1)) ; do echo b >> bout ; sleep 1 ; done ;} 
echo PID of loop2 $loop2_PID
coproc loop3 { while ((1)) ; do echo c >> cout ; sleep 1 ; done ;}
echo PID of loop3 $loop3_PID

sleep 2
kill $loop1_PID
sleep 2
kill $loop2_PID
sleep 2
kill $loop3_PID

IE

coproc NAME simple_command 
#or
coproc NAME { series ; of ; commands ;}

将存储 PID NAME_PID,稍后您可以使用它来终止该进程。


选择:虚拟文件

虽然使用 @αГsнιη 建议的 PID 是最正确的方法,但这里的另一个想法是创建一个虚拟文件:

 #!/bin/bash
 dummy="$(mktemp -u -p .)"
 ( while [ ! -e "$dummy" ] ; do ./async_command ; done ) &
 ...
 #condition met
 touch "$dummy"
 ...

您还可以使用此文件作为满足条件的指示符,或者trap如果您希望清理它,则添加一个。再次强调:通过 PID 进行控制应该是首选,但您可以滥用它来“命名”您的循环并停止正确的循环。

相关内容