在同一终端中一次并行运行多个命令


78

我想运行一些命令,直到按Ctrl-C才会退出。我是否可以运行一次即可运行所有这些程序,而Ctrl-C会全部退出它们?他们可以共享终端输出。

具体来说,我有指南针编译器,coffeescript编译器和一个监视文件更改的自定义命令,所有命令都在运行中监视文件更改。我不想为每个命令加载一个终端。

Answers:


122

该bash脚本适用于N个并行线程。每个参数都是一个命令。

trap捕获SIGINT时将杀死所有子进程。
wait $PID_LIST正在等待每个过程完成。所有过程完成后,程序退出。

#!/bin/bash

for cmd in "$@"; do {
  echo "Process \"$cmd\" started";
  $cmd & pid=$!
  PID_LIST+=" $pid";
} done

trap "kill $PID_LIST" SIGINT

echo "Parallel processes have started";

wait $PID_LIST

echo
echo "All processes have completed";

将此脚本另存为,parallel_commands并使其可执行。
这是使用此脚本的方法:

parallel_commands "cmd arg0 arg1 arg2" "other_cmd arg0 arg2 arg3"

例:

parallel_commands "sleep 1" "sleep 2" "sleep 3" "sleep 4"

启动4个并行睡眠,并等待直到“睡眠4”完成。


3
很酷。陷阱是我一直在寻找的东西。我将您的答案编辑为包括wait,这将消除不必要的“退出进程x”消息。
Oliver Zheng

1
@MTsoulwait优于while循环。我已经根据您的建议改进了我的脚本。现在它也适用于N个并行命令。
亚历山德罗·佩扎托

在单个核心上运行每个cmd怎么办?我应该像这样运行:./parallel_commands“ taskset -c 0 cmd arg0 arg1 arg2”“ taskset -c 1 other_cmd arg0 arg2 arg3”或taskset -c 2 ./parallel_commands“ taskset -c 0 cmd arg0 arg1 arg1 arg2”“ taskset -c 1 other_cmd arg0 arg2 arg3“
user2517676 2013年

很好。现在我有一些bash脚本中的命令,我想并行运行它们?
shgnInc

1
您要STDOUT还是退出值?
亚历山德罗·佩扎托

84

基于@ alessandro-pezzato的评论。通过&在命令之间使用来运行多个命令。

例:

$ sleep 3 & sleep 5 & sleep 2 &

它将在后台执行命令。


1
这就是我想要的。
TWR Cole

1
嗨@OleTange,我不知道有什么区别。我尝试过&!&并且两者均能正常工作。
nsantana

谢谢你的建议。我更改代码并删除感叹号。
nsantana'7

这样执行时,Control-C不会完全结束所有并行命令,它们将继续在后台运行。结束所有命令执行的正确方法是什么?
Cal S

运行fg,然后按Ctrl + C,然后根据需要重复操作
KTibow

35

使用GNU并行:

(echo command1; echo command2) | parallel
parallel ::: command1 command2

杀死:

parallel ::: command1 command2 &
PID=$!
kill -TERM $PID
kill -TERM $PID

1
@Oatman:应该的,但是并不是所有发行版中都包含GNU并行。例如,RHEL 7似乎没有易于使用的软件包。
Stefan Majewsky,

是否可以跟踪启动多个进程并通过终止父并行终止所有进程的并行进程的PID?
WM

@StefanMajewsky:parallel在EPEL存储库中。
匿名

引用警告/噪音真的很烦人!它会污染输出,您可以将其静音,但是为什么要这样做呢?想象一下,如果所有开放源代码工具都可以做到这一点的混乱!
Javad Sadeqzadeh,


3

可以使用简单的Makefile完成:

sleep%:
        sleep $(subst sleep,,$@)
        @echo $@ done.

使用-j选项。

$ make -j sleep3 sleep2 sleep1
sleep 3
sleep 2
sleep 1
sleep1 done.
sleep2 done.
sleep3 done.

如果没有-j选择,它将串行执行。

$ make -j sleep3 sleep2 sleep1
sleep 3
sleep3 done.
sleep 2
sleep2 done.
sleep 1
sleep1 done.

您也可以使用-n选项进行空运行。

$ make -j -n sleep3 sleep2 sleep1
sleep 3
sleep 2
sleep 1

1

我建议我写一个更简单的实用程序。它目前被称为par,但是不久之后将被重命名为parl或pll。

https://github.com/k-bx/par

API很简单:

par "script1.sh" "script2.sh" "script3.sh"

前缀命令可以通过以下方式完成:

par "PARPREFIX=[script1] script1.sh" "script2.sh" "script3.sh"

1
在尝试并无法使用gnu parallel完成上面描述的操作之后,我第一次尝试使用实用程序成功。干得好!
worldsayshi

第一个:parallel ::: "script1.sh" "script2.sh" "script3.sh"第二个通常会使用--tag: parallel --tag ::: "script1.sh" "script2.sh" "script3.sh"
Ole Tange

-12

要运行多个命令,只需&&在两个命令之间添加如下所示:command1 && command2

如果要在两个不同的终端中运行它们,则可以这样做:

gnome-terminal -e "command1" && gnome-terminal -e "command2"

这将打开2个终端,command1command2在其中执行。

希望这对您有所帮助。


4
这是不正确的。它仅在成功command2 之后 运行。尝试一下,您会发现它需要6秒钟。command1command1sleep 3 && sleep 3
Mark Setchell,

command1 && command2不会立即开始执行。它会一个接一个地执行(考虑命令的成功场景)。
加罕
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.