我正在尝试编写一个同时运行许多程序的.sh文件
我试过这个
prog1 prog2
但是运行prog1然后等到prog1结束然后开始prog2 ...
那我怎么能并行运行呢?
怎么样:
prog1 & prog2 && fg
这将:
开始prog1
.
将其发送到后台,但继续打印输出.
启动prog2
,并将其保持在前台,以便您可以将其关闭ctrl-c
.
当你关闭prog2
,你会回到prog1
的前景,所以你也可以关闭它ctrl-c
.
prog1 & prog2 &
使用GNU Parallel http://www.gnu.org/software/parallel/,它很简单:
(echo prog1; echo prog2) | parallel
或者如果您愿意:
parallel ::: prog1 prog2
学到更多:
观看介绍视频以获得快速介绍:https: //www.youtube.com/playlist?list = PL284C9FF2488BC6D1
阅读教程(man parallel_tutorial).你的命令行会爱你.
你可以使用wait
:
some_command & P1=$! other_command & P2=$! wait $P1 $P2
它将后台程序PID分配给变量($!
是最后一个启动的进程'PID),然后wait
命令等待它们.这很好,因为如果你杀死脚本,它也会杀死进程!
如果你想能够轻松地运行并杀死多个进程ctrl-c
,这是我最喜欢的方法:在(…)
子shell中生成多个后台进程,并SIGINT
执行trap kill 0
,这将杀死子shell组中生成的所有内容:
(trap 'kill 0' SIGINT; prog1 & prog2 & prog3)
你可以有复杂的流程执行结构,一切都将关闭单ctrl-c
(只需确保最后的过程是在前台运行,即没有一个包括&
后prog1.3
):
(trap 'kill 0' SIGINT; prog1.1 && prog1.2 & (prog2.1 | prog2.2 || prog2.3) & prog1.3)
#!/bin/bash prog1 & 2> .errorprog1.log; prog2 & 2> .errorprog2.log
将错误重定向到单独的日志.
有一个非常有用的程序叫nohup.
nohup - run a command immune to hangups, with output to a non-tty
xargs -P
允许您
并行运行命令。
尽管这-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
所有命令完成之前,命令本身不会返回,但是您可以在后台执行该操作&
,方法是使用控制操作符终止该命令,然后使用wait
内置函数等待整个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
要尽可能多的运行尽可能平行。
并行运行的进程的输出在生成时会到达,因此将无法预料地交错。
parallel
如Ole的回答中所述(大多数平台都不标准),GNU可以方便地在每个进程的基础上对输出进行序列化(分组),并提供更多高级功能。
你可以尝试ppss.ppss相当强大 - 你甚至可以创建一个迷你集群.如果你有一批令人尴尬的并行处理,xargs -P也很有用.
我最近有类似的情况,我需要同时运行多个程序,将它们的输出重定向到分离的日志文件并等待它们完成,我最终得到类似的东西:
#!/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/
这是我使用的函数,以便并行运行max n进程(在示例中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设置为内核数,则此函数将尝试避免空闲内核.