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

我试过了

prog1 
prog2

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

那么如何并行运行呢?


当前回答

如果你是:

在Mac上使用iTerm 想要启动各种长期打开的进程,直到按Ctrl+C 希望能够轻松地看到每个进程的输出 希望能够轻松地使用Ctrl+C停止特定进程

如果你的用例更多的是应用监控/管理,一种选择是编写终端本身的脚本。

例如,我最近做了以下事情。当然,它是特定于Mac的,特定于iTerm的,并且依赖于已弃用的Apple Script API (iTerm有一个更新的Python选项)。它没有赢得任何优雅奖,但完成了任务。

#!/bin/sh
root_path="~/root-path"
auth_api_script="$root_path/auth-path/auth-script.sh"
admin_api_proj="$root_path/admin-path/admin.csproj"
agent_proj="$root_path/agent-path/agent.csproj"
dashboard_path="$root_path/dashboard-web"

osascript <<THEEND
tell application "iTerm"
  set newWindow to (create window with default profile)

  tell current session of newWindow
    set name to "Auth API"
    write text "pushd $root_path && $auth_api_script"
  end tell

  tell newWindow
    set newTab to (create tab with default profile)
    tell current session of newTab
        set name to "Admin API"
        write text "dotnet run --debug -p $admin_api_proj"
    end tell
  end tell

  tell newWindow
    set newTab to (create tab with default profile)
    tell current session of newTab
        set name to "Agent"
        write text "dotnet run --debug -p $agent_proj"
    end tell
  end tell

  tell newWindow
    set newTab to (create tab with default profile)
    tell current session of newTab
        set name to "Dashboard"
        write text "pushd $dashboard_path; ng serve -o"
    end tell
  end tell

end tell
THEEND

其他回答

你可以使用wait:

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

它将后台程序pid分配给变量($!是最后启动进程的PID),然后wait命令等待它们。这很好,因为如果您终止了脚本,它也会终止进程!

这里有很多有趣的答案,但我从这个答案中获得了灵感,并将一个简单的脚本组合在一起,并行运行多个进程,并在完成后处理结果。你可以在以下要点中找到它:

#!/usr/bin/env bash

# inspired by https://stackoverflow.com/a/29535256/2860309

pids=""
failures=0

function my_process() {
    seconds_to_sleep=$1
    exit_code=$2
    sleep "$seconds_to_sleep"
    return "$exit_code"
}

(my_process 1 0) &
pid=$!
pids+=" ${pid}"
echo "${pid}: 1 second to success"

(my_process 1 1) &
pid=$!
pids+=" ${pid}"
echo "${pid}: 1 second to failure"

(my_process 2 0) &
pid=$!
pids+=" ${pid}"
echo "${pid}: 2 seconds to success"

(my_process 2 1) &
pid=$!
pids+=" ${pid}"
echo "${pid}: 2 seconds to failure"

echo "..."

for pid in $pids; do
        if wait "$pid"; then
                echo "Process $pid succeeded"
        else
                echo "Process $pid failed"
                failures=$((failures+1))
        fi
done

echo
echo "${failures} failures detected"

结果是:

86400: 1 second to success
86401: 1 second to failure
86402: 2 seconds to success
86404: 2 seconds to failure
...
Process 86400 succeeded
Process 86401 failed
Process 86402 succeeded
Process 86404 failed

2 failures detected

如果你想用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/

并行运行多个程序:

prog1 &
prog2 &

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

wait

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