我有一个异步 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 进行控制应该是首选,但您可以滥用它来“命名”您的循环并停止正确的循环。