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

我试过了

prog1 
prog2

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

那么如何并行运行呢?


当前回答

使用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

其他回答

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

将错误重定向到单独的日志。

这对我来说非常有用(在这里找到):

sh -c 'command1 & command2 & command3 & wait'

它混合输出每个命令的所有日志(这是我想要的),并使用ctrl+c杀死所有日志。

由于某些原因,我不能使用等待,我想出了这个解决方案:

# create a hashmap of the tasks name -> its command
declare -A tasks=(
  ["Sleep 3 seconds"]="sleep 3"
  ["Check network"]="ping imdb.com"
  ["List dir"]="ls -la"
)

# execute each task in the background, redirecting their output to a custom file descriptor
fd=10
for task in "${!tasks[@]}"; do
    script="${tasks[${task}]}"
    eval "exec $fd< <(${script} 2>&1 || (echo $task failed with exit code \${?}! && touch tasks_failed))"
    ((fd+=1))
done

# print the outputs of the tasks and wait for them to finish
fd=10
for task in "${!tasks[@]}"; do
    cat <&$fd
    ((fd+=1))
done

# determine the exit status
#   by checking whether the file "tasks_failed" has been created
if [ -e tasks_failed ]; then
    echo "Task(s) failed!"
    exit 1
else
    echo "All tasks finished without an error!"
    exit 0
fi

并行运行多个程序:

prog1 &
prog2 &

如果你需要脚本等待程序完成,你可以添加:

wait

在您希望脚本等待它们的地方。

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