如何从bash脚本并行运行多个程序?
我正在尝试编写一个同时运行多个程序的.sh文件
我试过这个
prog1 prog2
但是,运行prog1,然后等待prog1结束,然后启动prog2 …
那么我怎样才能平行运行呢?
prog1 & prog2 &
怎么样:
prog1 & prog2 && fg
这会:
- 开始
prog1
。 - 发送到后台,但不断打印输出。
- 启动
prog2
,并保持在前台 ,所以你可以用ctrl-c
closures它。 - 当你closures
prog2
,你将返回到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
要求你指定显式并行运行的命令的数量,而GNUxargs
允许你指定-P 0
来并行运行尽可能多的命令。 -
并行运行进程的输出在生成时就会到达,所以会不可预测地交错 。
- GNU
parallel
,正如Ole的回答中所提到的 (对于大多数平台来说并不是标准的),可以方便地按照每个进程序列化 (分组)输出,并提供许多更高级的function。
- GNU