我有一系列服务器,我想在这些服务器上运行相同的命令。每个命令都要花几个小时,而且(即使我使用 nohup 运行命令并将它们设置为在后台运行)我必须等待每个命令完成后才能开始下一个命令。以下是我大致的设置方式:
在主机上:
for i in {1..9}; do ssh RemoteMachine${i} ./RunJobs.sh; done
其中每台远程机器上的 RunJobs.sh 为:
source ~/.bash_profile
cd AriadneMatching
for file in FileDirectory/Input_*;
do
nohup ./Executable ${file} &
done
exit
有谁知道有一种方法可以让我不必等待每项工作完成后再开始下一项工作?或者有更好的方法,我感觉我的做法不太理想。谢谢,杰克
答案1
本地机器的解决方案
基于并行-ssh
# pssh -P --par 2 --hosts RemoteMachines /opt/RunJobs.sh
或者:
# pssh -i --par 2 --hosts RemoteMachines /opt/RunJobs.sh
解释参数:
-P
--print
Display output as it arrives. This option is of limited usefulness
because output from different hosts are interleaved.
-i
--inline
Display standard output and standard error as each host completes.
-p parallelism
--par parallelism
Use the given number as the maximum number of concurrent connections.
-h host_file
--hosts host_file
Read hosts from the given host_file.
基于ansible
# ansible --forks 2 -i RemoteMachines '*' -m command -a /opt/RunJobs.sh
解释参数:
-f NUM, --forks=NUM
Level of parallelism. NUM is specified as an integer, the default is 5.
-i PATH, --inventory=PATH
The PATH to the inventory hosts file, which defaults to /etc/ansible/hosts.
-m NAME, --module-name=NAME
Execute the module called NAME.
-a 'ARGUMENTS', --args='ARGUMENTS'
The ARGUMENTS to pass to the module.
这命令module 采用命令名称,后跟空格分隔的参数列表。给定的命令将在所有选定节点上执行。它不会通过 shell 处理,因此 $HOME 等变量以及“<”、“>”、“|”和“&”等操作将不起作用。
您可以在临时命令简介。
NB安塞波直到所有当前主机(“fork”)都完成之后,才会切换到下一组主机,因此其并行性较低比密码(可能有办法可以增加它,但我不知道)。
这远程机器对于这两种情况,文件看起来都是这样的:
[email protected]
[email protected]
[email protected]
[email protected]
远程机器的解决方案
改写运行作业变成这样:
find FileDirectory -name 'Input_*' -print0 | xargs -0 -P 2 -n 1 ./Executable
解释:
-0, --null
Input items are terminated by a null character instead of by
whitespace, and the quotes and backslash are not special (every
character is taken literally). Disables the end of file string,
which is treated like any other argument. Useful when input items
might contain white space, quote marks, or backslashes. The GNU find
-print0 option produces input suitable for this mode.
-P max-procs, --max-procs=max-procs
Run up to max-procs processes at a time; the default is 1. If
max-procs is 0, xargs will run as many processes as possible at a
time. Use the -n option or the -L option with -P; otherwise chances
are that only one exec will be done.
-n max-args, --max-args=max-args
Use at most max-args arguments per command line. Fewer than
max-args arguments will be used if the size (see the -s option) is
exceeded, unless the -x option is given, in which case xargs will
exit.
答案2
首先,您可能希望使用screen
而不是 来nohup
使会话在断开连接后继续存在。screen
为您提供一个稍后可以返回的虚拟终端。基本用法是screen yourcommand
执行yourcommand
并screen -DR
自动连接到现有会话,如果不存在则创建一个新会话。只需运行不带参数的 screen 也会在您可以使用的“屏幕”内为您提供提示。
其次,你可能需要研究GNU 并行对于并行作业。您可能不希望运行的进程多于 CPU 核心数,因为收益递减和磁盘过载。适合您的命令可能如下,同样,您必须在屏幕内运行它才能使其在断开连接后继续运行。
ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {}
列出您要处理的文件并通过管道传输到其中parallel
,指示运行 8 个并行作业并在当前目录中工作。
由于 screen 不理解作为参数给出的命令中的管道和其他内容 - 这是 shell 的工作 - 您需要将命令放在 shell 脚本中或给出 sh -c 命令来执行该命令。
screen sh -c 'ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {}'
或者简单地
screen ./runjob
其中runjob
包含:
#!/usr/bin/env bash
ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {}
答案3
使用屏幕在每台机器上,screen 启动一个命令(通常是一个 shell),它可以与你的 ssh 会话分离,以便它继续执行刚刚在其中启动的作业;换句话说,虽然该作业仍在运行,但当你注销时,不会被任何中断(不仅仅是 kill -9)打断。
当你愿意时,你可以通过 ssh 重新连接,并通过以下命令重新加入分离的会话
screen -r
这样就可以无缝地让你回到你放弃的 shell,同时向你显示你在此期间错过的所有标准输出(如果有)。
这样,您就不必等待任何事情,也不会有危险的挂起的 ssh 会话,如果意外断开连接,会导致您的工作失败。
屏幕在存储库中。
答案4
对于 {1..9} 中的 i;执行 ssh RemoteMachine${i} ./RunJobs.sh;完成
尝试这个
for i in {1..9}; do echo RemoteMachine${i}; done |xargs -I % -n 1 -P 10 ssh
% "./RunJobs.sh"
它的作用是构建一个机器名称列表,并将整个列表通过管道传输到 xargs。xargs 的参数含义为:
-I % 用第一个参数替换出现的 %
-n 1 每个命令行使用 1 个参数
-P 10 一次运行10个进程