运行 多个 exec 命令并在继续之前等待完成

Running multiple exec commands and waiting to finish before continuing

我知道我问了很多问题,我知道这里有很多关于这正是我想做的事情,但我无法让它在我的脚本中工作,也没有弄清楚为什么会这样不让我这样做。我正在尝试 运行 在后台使用 exec 的几个命令,测试的时间范围在 5 到 45 分钟之间(如果他们必须提示许可证,则更长)。 运行 他们背​​靠背需要很长时间,所以我想知道我需要做些什么才能让我的脚本等待他们完成,然后再继续下一部分脚本。

while {$cnt <= $len} {
# Begin count for running tests
set testvar [lindex $f $cnt]
if {[file exists $path0/$testvar] == 1} {
    cd $testvar
} else {
    exec mkdir $testvar
    cd $testvar
    exec create_symobic_link_here
}
# Set up test environment
exec -ignorestderr make clean
exec -ignorestderr make depends
puts "Running $testvar"
set runtest [eval exec -ignorestderr bsub -I -q lin_i make $testvar SEED=1 VPDDUMP=on |tail -n 1 >> $path0/runtestfile &]
cd ../
incr cnt
}

我知道这里没有任何东西可以让脚本等待进程完成,但我已经尝试了很多不同的东西,这是我可以得到 运行 一切的唯一方法。它只是不等待。

一种方法是修改测试以创建 "finished" 文件。无论测试正确完成还是失败,都应创建此文件。

修改启动循环以在开始测试之前删除此文件:

 catch { file delete $path0/$testvar/finished }

然后创建第二个循环:

while { true } {
  after 60000
  set cnt 1 ; # ?
  set result 0
  while { $cnt <= $len } {
    set testvar [lindex $f $cnt]
    if { [file exists $path0/$testvar/finished] } {
      incr result
    }
    incr cnt
  }
  if { $result == $len } {
    break
  }
}

如果任何一个测试没有创建 'finished' 文件,所写的这个循环将永远不会退出。所以我会添加一个额外的停止条件(不超过一小时)来退出循环。

另一种方法是将后台进程的进程 ID 保存在一个列表中,然后第二个循环将检查每个进程 ID 以查看它是否仍然是 运行。此方法不需要对测试进行任何修改,但实施起来有点困难(在 [=47= 上不太难,在 windows 上更难)。

编辑:循环使用进程 ID 检查:

要使用进程 ID,需要修改主循环以保存后台作业的进程 ID:

主循环开始前,清空进程id列表:

set pidlist {}

在主循环中,保存来自 exec 命令的进程 ID(在 tcl 中,[exec ... &] returns 后台进程 ID):

lappend pidlist $runtest ; # goes after the exec bsub...

检查进程是否存在的过程(针对 unix/mac)。 Tcl/Tk没有任何进程控制命令,所以使用unix 'kill'命令。 'kill -0'在unix上只检查进程是否存在,不影响进程的执行。

# return 0 if the process does not exist, 1 if it does
proc checkpid { ppid } {
  set pexists [catch {exec kill -0 $ppid}]
  return [expr {1-$pexists}]
}

检查测试是否完成的第二个循环变为:

set tottime 0
while { true } {
  after 60000
  incr tottime 1 ; # in minutes
  set result 0
  foreach {pid} $pidlist {
    if { ! [checkpid $pid] } {
      incr result
    }
  }
  if { $result == $len } {
    break
  }
  if { $tottime > 120 } {
    puts "Total test time exceeded."
    break ; # or exit 
  }
}

如果测试进程挂起并且永远不会退出,则此循环永远不会退出,因此使用总时间的第二个停止条件。