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

我试过了

prog1 
prog2

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

那么如何并行运行呢?


当前回答

下面是我为了并行运行最多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被设置为核数,该函数将尝试避免空闲核。

其他回答

如果你想用ctrl-c轻松地运行和杀死多个进程,这是我最喜欢的方法:在一个(…)subshell中生成多个后台进程,并捕获SIGINT来执行kill 0,这将杀死subshell组中生成的所有内容:

(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)

如果最后一个命令可能会提前退出,而您希望保持其他所有命令的运行,则添加wait作为最后一个命令。在下面的例子中,sleep 2会先退出,在sleep 4结束之前杀死它;添加wait可以让两者都运行到完成:

(trap 'kill 0' SIGINT; sleep 4 & sleep 2 & wait)

我最近遇到了类似的情况,我需要同时运行多个程序,将它们的输出重定向到独立的日志文件中,然后等待它们完成,最后我得到了这样的结果:

#!/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/

如果您有一个GUI终端,您可以为希望并行运行的每个进程生成一个新的选项卡终端实例。

这样做的好处是,每个程序都在自己的选项卡中运行,它可以独立于其他运行的程序进行交互和管理。

例如,在Ubuntu 20.04上:

gnome-terminal --tab -- bash -c 'prog1'
gnome-terminal --tab -- bash -c 'prog2'

要按顺序运行某些程序或其他命令,可以添加;

gnome-terminal --tab -- bash -c 'prog1_1; prog1_2'
gnome-terminal --tab -- bash -c 'prog2'

我发现对于某些程序,终端在启动之前就关闭了。对于这些程序,我将终端命令与;等待或;睡眠1

gnome-terminal --tab -- bash -c 'prog1; wait'

对于Mac OS,你必须为你正在使用的终端找到一个等效的命令——我没有在Mac OS上测试,因为我没有Mac。

如何:

prog1 & prog2 && fg

这将:

prog1开始。 将其发送到后台,但继续打印其输出。 启动prog2,并将其放在前台,因此可以使用ctrl-c关闭它。 当你关闭prog2时,你将返回到prog1的前台,所以你也可以用ctrl-c关闭它。

使用bashj (https://sourceforge.net/projects/bashj/),您不仅可以运行多个进程(其他人建议的方式),还可以在一个JVM中运行多个线程,这些线程由您的脚本控制。当然,这需要java JDK。线程比进程消耗更少的资源。

下面是一个工作代码:

#!/usr/bin/bashj

#!java

public static int cnt=0;

private static void loop() {u.p("java says cnt= "+(cnt++));u.sleep(1.0);}

public static void startThread()
{(new Thread(() ->  {while (true) {loop();}})).start();}

#!bashj

j.startThread()

while [ j.cnt -lt 4 ]
do
  echo "bash views cnt=" j.cnt
  sleep 0.5
done