我想编写一个.sh文件,可以同时运行多个程序。
我尝试了以下代码:
prog1
prog2
但是这样会运行prog1,等待直到程序结束,然后再开始运行prog2...
那么如何实现并行运行它们?
我想编写一个.sh文件,可以同时运行多个程序。
我尝试了以下代码:
prog1
prog2
但是这样会运行prog1,等待直到程序结束,然后再开始运行prog2...
那么如何实现并行运行它们?
如何尝试:
prog1 & prog2 && fg
这个命令会执行以下操作:
prog1
。prog2
并将其保持在前台,这样您可以使用 ctrl-c
来关闭它。prog2
后,您将返回到 prog1
的前台,因此您也可以使用 ctrl-c
关闭它。同时运行多个程序:
prog1 &
prog2 &
如果您需要脚本等待程序完成,可以添加:
wait
在您希望脚本等待它们的位置。
wait
命令!在Bash中,你可以等待脚本的子进程。 - Dummy00001nohup
命令,防止程序在 shell 断开连接时被终止。 - Philippprog1 | something & prog2 | another &
会怎么样呢?我很确定它不会起作用。 - Micha93如果你想要轻松地运行和终止多个进程,使用ctrl-c
,这是我最喜欢的方法:在一个(…)
子shell中生成多个后台进程,并捕获SIGINT
来执行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)
如果存在最后一条命令可能会提前退出并且您想让其他所有内容继续运行,请将wait
添加为最后一条命令。在以下示例中,sleep 2
将首先退出,杀死 sleep 4
,然后才能完成;添加wait
允许两者都运行到完成:
(trap 'kill 0' SIGINT; sleep 4 & sleep 2 & wait)
(trap 'kill 0' SIGINT; prog1 & prog2 & prog3 & wait)
有助于确保所有程序都能顺利完成。 - jakeonfire您可以使用wait
:
some_command &
P1=$!
other_command &
P2=$!
wait $P1 $P2
它将后台程序的PID分配给变量($!
是最后启动的进程的PID),然后wait
命令等待它们。如果你杀死脚本,它也会杀死这些进程,这很好!
wait
无法结束我的第二个进程。 - frodo2975使用GNU Parallel http://www.gnu.org/software/parallel/,操作起来非常简单:
(echo prog1; echo prog2) | parallel
或者如果您更喜欢:
parallel ::: prog1 prog2
了解更多信息:
parallel
存在不同语法的不同版本。例如,在 Debian 派生系统中,moreutils
软件包包含一个名为 parallel
的不同命令,其行为有很大不同。 - Joel Crossxargs -P <n>
允许您并行运行 <n>
个命令。
虽然 -P
是一个非标准选项,但 GNU (Linux) 和 macOS/BSD 实现都支持它。
下面的例子:
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
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
(大多数平台不自带)方便地按照每个进程的基础对输出进行序列化(分组),并提供了许多高级功能。这是一个我用来最多并行运行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 设为核心数量,此函数将尝试避免空闲的核心。
#!/bin/bash
prog1 & 2> .errorprog1.log; prog2 & 2> .errorprog2.log
将错误重定向到单独的日志中。
prog1 2> .errorprog1.log & prog2 2> .errorprog2.log &
- Dennis Williamsonls notthere1 & 2> .errorprog1.log; ls notthere2 & 2>.errorprog2.log
。错误信息会输出到控制台,两个错误文件都是空的。正如@Dennis Williamson所说,&
是一个分隔符,就像;
一样,所以(a)它需要放在命令的末尾(在任何重定向之后),(b)你根本不需要;
:-) - psmearssh -c 'command1 & command2 & command3 & wait'
ctrl+c
时,子进程不会在后台继续运行吗? - Leonardo Raele有一个非常有用的程序叫做 nohup。
nohup - run a command immune to hangups, with output to a non-tty
nohup
命令本身并不会将任何东西放在后台运行,使用 nohup
也不是在后台运行任务的必要条件或前提。虽然它们经常一起使用,但这并不能回答问题。 - tripleee
prog2
终止时,是否有一种简单的方法来终止prog1
?请考虑node srv.js&cucumberjs
。 - jpsecherprog1&prog2; fg
这是为了同时运行多个ssh隧道。希望能对某些人有所帮助。 - jnadro52prog2
无法立即运行,你将回到在前台运行prog1
的状态。如果这是可取的,那就没问题。 - Ory Bandprog1&prog2 && kill $!
。 - zaboco