如何从bash脚本并行运行多个程序?

我正在尝试编写一个同时运行多个程序的.sh文件

我试过这个

prog1 prog2 

但是,运行prog1,然后等待prog1结束,然后启动prog2 …

那么我怎样才能平行运行呢?

 prog1 & prog2 & 

怎么样:

 prog1 & prog2 && fg 

这会:

  1. 开始prog1
  2. 发送到后台,但不断打印输出。
  3. 启动prog2 ,并保持在前台 ,所以你可以用ctrl-cclosures它。
  4. 当你closuresprog2 ,你将返回到prog1前景 ,所以你也可以用ctrl-c来closures它。

使用GNU并行http://www.gnu.org/software/parallel/就像下面这样简单:;

 (echo prog1; echo prog2) | parallel 

或者如果你喜欢:

 parallel ::: prog1 prog2 

学到更多:

  • 观看介绍video快速介绍: https : //www.youtube.com/playlist?list=PL284C9FF2488BC6D1
  • 浏览教程(man parallel_tutorial)。 你的命令行会爱你。

你可以用wait

 some_command & P1=$! other_command & P2=$! wait $P1 $P2 

它将后台程序PID分配给variables( $!是最后启动的进程的PID),然后wait命令等待它们。 这很好,因为如果你杀死脚本,它也会杀死进程!

 #!/bin/bash prog1 & 2> .errorprog1.log; prog2 & 2> .errorprog2.log 

redirect错误以分隔日志。

有一个非常有用的程序,叫nohup。

  nohup - run a command immune to hangups, with output to a non-tty 

你可以试试ppss 。 ppss是相当强大的 – 你甚至可以创build一个小型集群。 xargs -P也可以是有用的,如果你有一批尴尬的并行处理。

最近我有类似的情况,我需要同时运行多个程序,将他们的输出redirect到分离的日志文件,等待他们完成,我最终得到了类似的东西:

 #!/bin/bash # Add the full path processes to run to the array PROCESSES_TO_RUN=("/home/joao/Code/test/prog_1/prog1" \ "/home/joao/Code/test/prog_2/prog2") # You can keep adding processes to the array... for i in ${PROCESSES_TO_RUN[@]}; do ${i%/*}/./${i##*/} > ${i}.log 2>&1 & # ${i%/*} -> Get folder name until the / # ${i##*/} -> Get the filename after the / done # Wait for the processes to finish wait 

资料来源: http : //joaoperibeiro.com/execute-multiple-programs-and-redirect-their-outputs-linux/

下面是一个函数,我用它来并行执行最大进程(n = 4)。

 max_children=4 function parallel { local time1=$(date +"%H:%M:%S") local time2="" # for the sake of the example, I'm using $2 as a description, you may be interested in other description echo "starting $2 ($time1)..." "$@" && time2=$(date +"%H:%M:%S") && echo "finishing $2 ($time1 -- $time2)..." & local my_pid=$$ local children=$(ps -eo ppid | grep -w $my_pid | wc -w) children=$((children-1)) if [[ $children -ge $max_children ]]; then wait -n fi } parallel sleep 5 parallel sleep 6 parallel sleep 7 parallel sleep 8 parallel sleep 9 wait 

如果max_children设置为核心数量,此function将尝试避免空闲核心。

xargs -P <n>允许您并行运行<n>命令。

虽然-P是非标准选项,但GNU(Linux)和macOS / BSD实现都支持它。

下面的例子:

  • 一次最多并行运行3个命令,
  • 只有当以前启动的进程终止时才会启动附加的命令。
 time xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF' sleep 1; echo 1 sleep 2; echo 2 sleep 3; echo 3 echo 4 EOF 

输出看起来像是:

 1 # output from 1st command 4 # output from *last* command, which started as soon as the count dropped below 3 2 # output from 2nd command 3 # output from 3rd command real 0m3.012s user 0m0.011s sys 0m0.008s 

时间表明这些命令是并行运行的(最后一个命令是在原始3的第一个终止后才启动的,但是执行得非常快)。

在所有命令完成之前, xargs命令本身不会返回,但是您可以在后台通过使用控制运算符&终止它,然后使用内build等待来等待整个xargs命令完成。

 { xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF' sleep 1; echo 1 sleep 2; echo 2 sleep 3; echo 3 echo 4 EOF } & # Script execution continues here while `xargs` is running # in the background. echo "Waiting for commands to finish..." # Wait for `xargs` to finish, via special variable $!, which contains # the PID of the most recently started background process. wait $! 

注意:

  • BSD / macOS xargs要求你指定显式并行运行的命令的数量,而GNU xargs允许你指定-P 0来并行运行尽可能多的命令。

  • 并行运行进程的输出在生成时就会到达,所以会不可预测地交错

    • GNU parallel ,正如Ole的回答中所提到的 (对于大多数平台来说并不是标准的),可以方便地按照每个进程序列化 (分组)输出,并提供许多更高级的function。