bash 如何通过 SSH 自动将命令远程并行运行到多个服务器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/243750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I automate running commands remotely over SSH to multiple servers in parallel?
提问by f4nt
I've searched around a bit for similar questions, but other than running one command or perhaps a few command with items such as:
我已经搜索了一些类似的问题,但除了运行一个命令或可能包含以下项目的几个命令之外:
ssh user@host -t sudo su -
However, what if I essentially need to run a script on (let's say) 15 servers at once. Is this doable in bash? In a perfect world I need to avoid installing applications if at all possible to pull this off. For argument's sake, let's just say that I need to do the following across 10 hosts:
但是,如果我基本上需要同时在(假设)15 个服务器上运行一个脚本,该怎么办。这在 bash 中可行吗?在一个完美的世界中,如果可能的话,我需要避免安装应用程序来实现这一点。为了论证,我们假设我需要在 10 台主机上执行以下操作:
- Deploy a new Tomcat container
- Deploy an application in the container, and configure it
- Configure an Apache vhost
- Reload Apache
- 部署一个新的Tomcat容器
- 在容器中部署一个应用,并配置它
- 配置 Apache 虚拟主机
- 重新加载阿帕奇
I have a script that does all of that, but it relies on me logging into all the servers, pulling a script down from a repo, and then running it. If this isn't doable in bash, what alternatives do you suggest? Do I need a bigger hammer, such as Perl (Python might be preferred since I can guarantee Python is on all boxes in a RHEL environment thanks to yum/up2date)? If anyone can point to me to any useful information it'd be greatly appreciated, especially if it's doable in bash. I'll settle for Perl or Python, but I just don't know those as well (working on that). Thanks!
我有一个脚本可以完成所有这些,但它依赖于我登录所有服务器,从存储库中提取脚本,然后运行它。如果这在 bash 中不可行,您有什么建议?我是否需要一个更大的锤子,比如 Perl(Python 可能是首选,因为我可以保证 Python 在 RHEL 环境中的所有机器上都使用 yum/up2date)?如果有人可以向我指出任何有用的信息,我将不胜感激,特别是如果它在 bash 中可行。我会满足于 Perl 或 Python,但我只是不知道那些(正在研究)。谢谢!
采纳答案by brian d foy
Often, I'll just use the original Tcl version of Expect. You only need to have that on the local machine. If I'm inside a program using Perl, I do this with Net::SSH::Expect. Other languages have similar "expect" tools.
通常,我只会使用 Expect 的原始 Tcl 版本。你只需要在本地机器上拥有它。如果我在使用 Perl 的程序中,我会使用Net::SSH::Expect执行此操作。其他语言也有类似的“期望”工具。
回答by Bash
You can run a local script as shown by che and Yang, and/or you can use a Here document:
您可以运行 che 和 Yang 所示的本地脚本,和/或您可以使用 Here 文档:
ssh root@server /bin/sh <<\EOF
wget http://server/warfile # Could use NFS here
cp app.war /location
command 1
command 2
/etc/init.d/httpd restart
EOF
回答by Philip Durbin
The issue of how to run commands on many servers at once came up on a Perl mailing list the other day and I'll give the same recommendation I gave there, which is to use gsh
:
如何一次在多台服务器上运行命令的问题前几天出现在 Perl 邮件列表中,我将给出我在那里给出的相同建议,即使用gsh
:
http://outflux.net/unix/software/gsh
http://outflux.net/unix/software/gsh
gsh is similar to the "for box in box1_name box2_name box3_name
" solution already givenbut I find gsh to be more convenient. You set up a /etc/ghosts file containing your servers in groups such as web, db, RHEL4, x86_64, or whatever (man ghosts) then you use that group when you call gsh.
gsh 类似于已经给出的“ for box in box1_name box2_name box3_name
”解决方案,但我发现 gsh 更方便。您设置了一个 /etc/ghosts 文件,其中包含您的服务器,例如 web、db、RHEL4、x86_64 或其他任何(man ghosts)组,然后在调用 gsh 时使用该组。
[pdurbin@beamish ~]$ gsh web "cat /etc/redhat-release; uname -r"
www-2.foo.com: Red Hat Enterprise Linux AS release 4 (Nahant Update 7)
www-2.foo.com: 2.6.9-78.0.1.ELsmp
www-3.foo.com: Red Hat Enterprise Linux AS release 4 (Nahant Update 7)
www-3.foo.com: 2.6.9-78.0.1.ELsmp
www-4.foo.com: Red Hat Enterprise Linux Server release 5.2 (Tikanga)
www-4.foo.com: 2.6.18-92.1.13.el5
www-5.foo.com: Red Hat Enterprise Linux Server release 5.2 (Tikanga)
www-5.foo.com: 2.6.18-92.1.13.el5
[pdurbin@beamish ~]$
You can also combine or split ghost groups, using web+db or web-RHEL4, for example.
例如,您还可以使用 web+db 或 web-RHEL4 组合或拆分幽灵组。
I'll also mention that while I have never used shmux, its websitecontains a list of software (including gsh) that lets you run commands on many servers at once. Capistranohas already been mentioned and (from what I understand) could be on that list as well.
我还要提一下,虽然我从未使用过 shmux,但它的网站包含一个软件列表(包括 gsh),可让您一次在多台服务器上运行命令。 Capistrano已经被提及并且(据我所知)也可能在该列表中。
回答by antik
Take a look at Expect (man expect
)
看看期待 ( man expect
)
I've accomplished similar tasks in the past using Expect.
我过去曾使用 Expect 完成过类似的任务。
回答by Yang Zhao
You can pipe the local script to the remote server and execute it with one command:
您可以将本地脚本通过管道传输到远程服务器并使用一个命令执行它:
ssh -t user@host 'sh' < path_to_script
This can be further automated by using public key authentication and wrapping with scripts to perform parallel execution.
这可以通过使用公钥身份验证和用脚本包装来执行并行执行来进一步自动化。
回答by Christopher Mahan
You can try paramiko. It's a pure-python ssh client. You can program your ssh sessions. Nothing to install on remote machines.
你可以试试paramiko。它是一个纯 python ssh 客户端。您可以对 ssh 会话进行编程。无需在远程机器上安装。
See this great articleon how to use it.
回答by Darron
To give you the structure, without actual code.
给你结构,没有实际代码。
- Use scp to copy your install/setup script to the target box.
- Use ssh to invoke your script on the remote box.
- 使用 scp 将您的安装/设置脚本复制到目标框。
- 使用 ssh 在远程设备上调用您的脚本。
回答by Brad Montgomery
For those that stumble across this question, I'll include an answer that uses Fabric, which solves exactly the problem described above: Running arbitrary commands on multiple hosts over ssh.
对于那些偶然发现这个问题的人,我将提供一个使用Fabric的答案,它完全解决了上述问题:通过 ssh 在多个主机上运行任意命令。
Once fabric is installed, you'd create a fabfile.py
, and implement tasksthat can be run on your remote hosts. For example, a task to Reload Apachemight look like this:
安装结构后,您将创建一个fabfile.py
,并实现可以在远程主机上运行的任务。例如,重新加载 Apache的任务可能如下所示:
from fabric.api import env, run
env.hosts = ['[email protected]', '[email protected]']
def reload():
""" Reload Apache """
run("sudo /etc/init.d/apache2 reload")
Then, on your local machine, run fab reload
and the sudo /etc/init.d/apache2 reload
command would get run on all the hosts specified in env.hosts
.
然后,在您的本地计算机上运行fab reload
,该sudo /etc/init.d/apache2 reload
命令将在 中指定的所有主机上运行env.hosts
。
回答by bortzmeyer
psshmay be interesting since, unlike most solutions mentioned here, the commands are run in parallel.
pssh可能很有趣,因为与这里提到的大多数解决方案不同,这些命令是并行运行的。
(For my own use, I wrote a simpler small script very similar to GavinCattell's one, it is documented here - in french).
(为了我自己的使用,我写了一个更简单的小脚本,与 GavinCattell 的脚本非常相似,这里有记录 - 法语)。