调用多个bash脚本并并行运行,而不是依次运行


19

假设我有三个(或更多)的bash脚本:script1.shscript2.sh,和script3.sh。我想调用所有这三个脚本并并行运行它们。一种方法是仅执行以下命令:

nohup bash script1.sh &
nohup bash script2.sh &
nohup bash script3.sh &

(通常,脚本可能需要几个小时或几天才能完成,所以我想使用nohup它们,以便即使我的控制台关闭也可以继续运行。)

但是,有什么方法可以通过一次调用并行执行这三个命令?

我在想类似

nohup bash script{1..3}.sh &

但这似乎是按顺序执行script1.shscript2.shscript3.sh不是并行执行。


2
“单次通话”是什么意思?
jw013

1
用例是什么?您有一百万个脚本可以启动吗?
l0b0

@ jw013我的意思是,就像一个短线命令一样。如果我有100个脚本要启动,我希望能够键入简短的内容(例如nohup bash script{1..100}.sh &for i in {1..100}; do nohup bash script{1..100} &; done),而不是键入nohup bash script*.sh &100次不同的时间。
2014年

1
如果脚本具有有用的输出:您也可以在screen(或tmux)中启动它们,以解决控制台问题,但仍可访问输出(和输入)。
Hauke Laging

1
没有什么可以阻止您在同一行中键入所有这三个命令。nohup ... & nohup ... & nohup ... &。相反,如果您要运行所有脚本而不单独键入每个脚本名称,那么将执行一个简单的循环。
jw013

Answers:



14

更好的方法是使用GNU Parallel。GNU并行很简单,有了它,我们可以控制要并行运行的作业数量,并且可以更好地控制这些作业。

在下面的命令中,script{1..3}.sh被扩展并作为参数发送到bash并行。此处-j0指示应运行尽可能多的作业。默认情况下parallel,一个cpu核心运行一个作业。

$ parallel -j0 bash :::: <(ls script{1..3}.sh)

您也可以尝试使用

$ parallel -j0 bash ::: script{1..3}.sh

在执行第二种方法时,如果收到任何错误消息,则意味着--tollef已设置该选项/etc/parallel/config,需要将其删除,并且一切正常。

您可以在此处阅读GNU Parallels手册页以获取更丰富的选项。

而且,如果您正在从远程计算机上运行作业,请更好地使用它,screen以免由于网络问题而关闭会话。nohup不需要,因为最新版本的bash随huponexitas 一起提供off,这将防止父shell HUP在退出时向其子进程发送信号。如果未设置,请使用

$ shopt -u huponexit  

如果你要使用bash的外壳parallel -j0 bash :::: <(ls script{1..3}.sh)可以降低到parallel -j0 bash :::: script{1..3}.sh,不是吗?
iruvar 2014年

并非没有,当与'::::'并行使用时,表示参数是一个文件,其中包含要执行的命令,而不是命令本身。在这里,我们使用进程替换来重定向文件描述符中的脚本名称。
Kannan Mohan 2014年

呃..在那种情况下为什么不parallel -j0 bash ::: script{1..3}.sh呢?
iruvar

bash ::: script{1..3}.sh被传递给parallel,而不是::: script{1..3}.sh。因此,这首先应扩大到 parallel bash ::: script1.sh script2.sh script3.sh由外壳,然后parallel的调用bash script1.shbash script2.shbash script3.sh。我尝试过
iruvar

1
不,我不感到困惑,我要说的是可以更好地解决OP的问题parallel -j0 bash ::: script{1..3}.sh-这比::::方法更好,因为它避免了流程替换的需要。还解析LS输出骑与陷阱
iruvar

9

我们还可以xargs用来并行运行多个脚本。

$ ls script{1..5}.sh|xargs -n 1 -P 0 bash

在这里,每个脚本分别作为参数传递给bash。-P 0表示并行处理的数量可以尽可能多。使用bash default更安全job control feature (&)


5

单个线的解决方案:

$ nohup bash script1.sh & nohup bash script2.sh & nohup bash script3.sh &

毫不费力地,只需使用包装器脚本即可:

$ cat script.sh
#!/usr/bin/env bash
script1.sh &
script2.sh &
script3.sh &
$ nohup script.sh &

或循环遍历它们:

for script in dir/*.sh
do
    nohup bash "$script" &
done

2

如果您想节省一些打字工作

eval "nohup bash "script{1..3}.sh" &"

或再三考虑,也许不是


1

签出此工具:https : //github.com/wagoodman/bashful

假设你有mytasks.yaml

tasks:
    - name: A title for some tasks
      parallel-tasks:
        - cmd: ./script1.sh
        - cmd: ./script2.sh -x an-arg
        - cmd: ./script3.sh -y some-other-arg

您可以像这样运行它:

nohup bashful run mytasks.yaml

您的脚本将与垂直进度条并行运行(如果您之前运行过脚本且时间是确定的,则为+ eta)。如果您开始运行的任务不只是给定的3个,则可以调整要并行运行的任务数:

config:
    max-parallel-commands: 6
tasks:
    ...

免责声明:我是作者。



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.