在Paralell Bash中运行Serial

我已经加了一点我的解释。 从概念上讲,我正在运行一个脚本,它循环处理,调用使用行内容作为input参数的shell。(FYI:a启动执行,b监视执行)

  1. 我需要1a和1b先运行,并行前两个$ param
  2. 接下来,当步骤1完成时,2a和2b需要以$ params的顺序运行
  3. 3a和3b将在2a和2b完成后启动(串行或并行不相关)
  4. 循环继续从input.txt的下两行

我不能得到它在串行处理第二,只有所有并行:我需要的是以下

cat filename | while readline export param=$line do ./script1a.sh "param" > process.lg && ./script2b.sh > monitor.log && ##wait for processes to finish, running 2 in parallel in script1.sh ./script2a.sh "param" > process2.log && ./script2b.sh > minitor2.log && ##run each of the 2 in serial for script2.sh ./script3a.sh && ./script3b.sh 

我尝试join等待,并尝试了一个if语句包含script2a.sh和script2b.sh将串行运行,但无济于事。

 if ((++i % 2 ==0)) then wait fi done #only run two lines at a time, then cycle back through loop 

我怎么能得到script2.sh并行运行的脚本1并行?

您没有向我们展示从文件中读取的行是如何被使用的。
如果我正确地理解了你的问题,你想要在两行filename运行script1 ,每个script2都是并行的,然后在两者都完成的情况下连续运行script2

 while read first; do echo "$first" | ./script1.sh & read second echo "$second" | ./script1.sh & wait script2.sh & # optionally don't background here? script3.sh done <filename & 

while循环包含两个read语句,因此每个迭代从filename读取两行,并将每个行提供给一个单独的script1实例。 然后wait两者都完成之后再运行script2 。 我将它背景化以便script3可以在运行时启动,并且可以在整个while循环中进行后台运行; 但是您可能实际上并不需要默认背景(如果您将其作为常规前台作业编写,那么开发将会容易得多,如果需要的话,在启动时将其背景化)。

我可以根据你实际上希望你的数据流动的情况考虑一些变化。 这里是针对您最近更新的问题的更新。

 export param # is this really necessary? while read param; do # First instance ./script1a.sh "$param" > process.lg && ./script2b.sh > monitor.log & # Second instance read param ./script2a.sh "$param" > process2.log && ./script2b.sh > minitor2.log & # Wait for both to finish wait ./script3a.sh && ./script3b.sh done <filename 

如果这仍然没有帮助,也许你应该发表第三个问题,你真正解释你想要什么…

锁定!

如果要并行化script1script3 ,但需要序列化script2所有调用,请继续使用:

 ./script1.sh && ./script2.sh && ./script3.sh & 

…但是修改script2以在别的之前抓住一个锁:

 #!/bin/bash exec 3>.lock2 flock -x 3 # ... continue with script2's business here. 

请注意,您不得删除此处使用的.lock2文件,这可能会导致多个进程认为它们同时持有锁。

我不是100%确定你的问题是什么意思,但现在我认为你的意思是在你的内部循环中是这样的:

 ( # run script1 and script2 in parallel script1 & s1pid=$! # start no more than one script2 using GNU Parallel as a mutex sem --fg script2 # when they are both done... wait $s1pid # run script3 script3 ) & # and do that lot in parallel with previous/next loop iteration 

@tripleee如果感兴趣的话,我把以下内容放在一起(注意:我改变了这个帖子的一些变量,所以很抱歉,如果有任何地方的不一致…也出口有他们的原因。我认为有一个比出口更好的方式,但现在作品)

 cat input.txt | while read first; do export step=${first//\"/} export stepem=EM_${step//,/_} export steptd=TD_${step//,/_} export stepeg=EG_${step//,/_} echo "$step" | $directory"/ws_client.sh" processOptions "$appName" "$step" "$layers" "$stages" "" "$stages" "$stages" FALSE > "$Folder""/""$stepem""_ProcessID.log" && $dir_model"/check_ status.sh" "$Folder" "$stepem" > "$Folder""/""$stepem""_Monitor.log" & read second export step2=${second//\"/} export stepem2=ExecuteModel_${step2//,/_} export steptd2=TransferData_${step2//,/_} export stepeg2=ExecuteGeneology_${step2//,/_} echo "$step2" | $directory"/ws_client.sh" processOptions "$appName" "$step2" "$layers" "$stages" "" "$stages" "$stages" FALSE > "$Folder""/""$stepem2""_ProcessID.log" && $dir _model"/check _status.sh" "$Folder" "$stepem2" > "$Folder""/""$stepem2""_Monitor.log" & wait $directory"/ws_client.sh" processOptions "$appName" "$step" "$layers" "" "" "$stage_final" "" TRUE > "$appLogFolder""/""$steptd""_ProcessID.log" && $dir _model"/check_status.sh" "$Folder" "$steptd" > "$Folder""/""$steptd""_Monitor.log" && $directory"/ws_client.sh" processOptions "$appName" "$step2" "$layers" "" "" "$stage_final" "" TRUE > "$appLogFolder""/""$steptd2""_ProcessID.log" && $dir _model"/check _status.sh" "$Folder" "$steptd2" > "$Folder""/""$steptd2""_Monitor.log" & wait $directory"/ws_client.sh" processPaths "$appName" "$step" "$layers" "$genPath_01" > "$appLogFolder""/""$stepeg""_ProcessID.log" && $dir _model"/check _status.sh" "$Folder" "$stepeg" > "$Folder""/""$stepeg""_Monitor.log" && $directory"/ws_client.sh" processPaths "$appName" "$step2" "$layers" "$genPath_01" > "$appLogFolder""/""$stepeg2""_ProcessID.log" && $dir_model"/check _status.sh" "$Folder" "$stepeg2" > "$Folder""/""$stepeg2""_Monitor.log" & wait if (( ++i % 2 == 0)) then echo "Waiting..." wait fi 

我理解你的问题,如:

你有一个模型列表。 这些模型需要运行。 他们运行后,他们必须转移。 简单的解决方案是:

 run_model model1 transfer_result model1 run_model model2 transfer_result model2 

但为了使这个更快,我们想要平行化部分。 不幸的是, transfer_result不能并行化。

 run_model model1 run_model model2 transfer_result model1 transfer_result model2 

model1model2是从文本文件中读取的。 run_model可以并行运行,并且你需要2个并行运行的程序。 transfer_result只能一次运行一个,只有在计算结果后才能传输结果。

这可以这样做:

 cat models.txt | parallel -j2 'run_model {} && sem --id transfer transfer_model {}' 

run_model {} && sem --id transfer transfer_model {}将运行一个模型,如果成功传输它。 只有在没有其他传输正在运行的情况下才能启动传输。

parallel -j2parallel -j2运行这两个作业。

如果转移比计算模型短,那么您不应该感到惊讶:转移最多只能与下一次转移交换。 如果转移比运行模型花费的时间更长,您可能会发现模型完全无序转移(例如,您可能会在转移作业2之前看到转移作业10)。 但他们最终都会被转移。

你可以看到这个例子的执行顺序:

 seq 10 | parallel -uj2 'echo ran model {} && sem --id transfer "sleep .{};echo transferred {}"' 

此解决方案比基于wait的解决方案更好,因为您可以在model1 + 2正在传输时运行model3。