Bash循环中如何等待命令执行完成并设置最长超时时间
问题1:实现循环内命令执行完成后再运行下一轮
首先纠正你对&的误解:Bash中命令末尾加&的作用是将命令放到后台异步执行,主脚本不会等待该命令结束就会直接执行后续逻辑,这也是你当前没有生效的原因。
想要实现同步等待,直接去掉make命令末尾的&即可,基础版脚本如下:
for k in $(seq 1 5) do sed_param='s/mu = .*/mu = '${mu}';/' sed -i "$sed_param" brusselator.c # 去掉&后,脚本会阻塞等待make执行完成,再进入下一轮循环 make brusselator.tst done
问题2:实现命令最长等待5秒、超时自动终止
这里提供两种常用的实现方案:
方案1:使用系统自带timeout命令(推荐)
绝大多数Linux发行版都预装了timeout工具,可以直接实现超时控制逻辑:命令提前执行完成就直接返回,达到指定时长未完成就自动终止进程,脚本示例如下:
for k in $(seq 1 5) do sed_param='s/mu = .*/mu = '${mu}';/' sed -i "$sed_param" brusselator.c # 最多等待5秒,超时自动终止make进程 timeout 5s make brusselator.tst # 可选:判断是否超时,超时的返回值固定为124 if [ $? -eq 124 ]; then echo "第${k}次执行make超时,已自动终止" fi done
注意:如果默认终止信号无法结束进程,可以指定发送强杀信号,写法为
timeout -s 9 5s make brusselator.tst
方案2:纯Bash实现(适配无timeout的环境)
如果运行环境没有预装timeout,可以通过后台进程+主动检查存活的逻辑自行实现超时控制:
for k in $(seq 1 5) do sed_param='s/mu = .*/mu = '${mu}';/' sed -i "$sed_param" brusselator.c # 把make放到后台运行,记录进程ID make brusselator.tst & make_pid=$! # 最多等待5秒,每秒检查一次进程存活状态 wait_seconds=0 while kill -0 $make_pid 2>/dev/null && [ $wait_seconds -lt 5 ]; do sleep 1 wait_seconds=$((wait_seconds+1)) done # 超时后进程仍存活则主动杀掉 if kill -0 $make_pid 2>/dev/null; then kill $make_pid 2>/dev/null # 回收进程资源避免僵尸进程 wait $make_pid 2>/dev/null echo "第${k}次执行make超时,已手动终止" fi done
内容的提问来源于stack exchange,提问作者Caspertijmen1
相关产品推荐
相关产品推荐

