如何通过 SSH 自动并行运行命令到多个服务器?

发布于 2024-07-08 12:44:30 字数 608 浏览 9 评论 0原文

我已经搜索了一些类似的问题,但除了运行一个命令或可能包含以下项目的几个命令之外:

ssh user@host -t sudo su -

但是,如果我本质上需要同时在(比方说)15 台服务器上运行一个脚本怎么办? 这在 bash 中可行吗? 在完美的世界中,如果可能的话,我需要避免安装应用程序来实现这一目标。 为了便于讨论,我们假设我需要在 10 个主机上执行以下操作:

  1. 部署一个新的 Tomcat 容器
  2. 在容器中部署一个应用程序,并配置它
  3. 配置一个 Apache 虚拟主机
  4. 重新加载 Apache

我有一个脚本可以完成所有这些操作,但是它依赖于我登录所有服务器,从存储库中提取脚本,然后运行它。 如果这在 bash 中不可行,你建议什么替代方案? 我是否需要更大的锤子,例如 Perl(Python 可能是首选,因为我可以保证 Python 出现在 RHEL 环境中的所有机器上,这要归功于 yum/up2date)? 如果有人能向我指出任何有用的信息,我将不胜感激,特别是如果它可以在 bash 中实现。 我会选择 Perl 或 Python,但我只是不太了解这些(正在研究)。 谢谢!

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:

  1. Deploy a new Tomcat container
  2. Deploy an application in the container, and configure it
  3. Configure an Apache vhost
  4. Reload 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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(20

爱她像谁 2024-07-15 12:44:31

好吧,对于步骤 1 和 2,没有 tomcat 管理器 Web 界面吗? 您可以使用带有 libwww 插件的 curl 或 zsh 编写脚本。

对于 SSH,您需要:
1)不提示输入密码(使用密钥)
2) 在 SSH 命令行上传递命令,这类似于受信任网络中的 rsh。

其他帖子已经向您展示了该怎么做,我可能也会使用 sh 但我很想使用 perl 就像 ssh tomcatuser@server perl - e 'do-everything-on-one-line;' 或者您可以这样做:

任一 scp the_package.tbz tomcatuser@server:the_place/。< br>
ssh tomcatuser@server /bin/sh <<\EOF
定义类似 TOMCAT_WEBAPPS=/usr/local/share/tomcat/webapps
tar xj the_package.tbz rsync rsync://repository/the_package_place
mv $TOMCAT_WEBAPPS/old_war $TOMCAT_WEBAPPS/old_war.old
mv $THE_PLACE/new_war $TOMCAT_WEBAPPS/new_war
touch $TOMCAT_WEBAPPS/new_war [通常不需要重新启动 tomcat]
mv $THE_PLACE/vhost_file $APACHE_VHOST_DIR/vhost_file
$APACHECTL restart [可能需要以 apache 用户身份登录才能移动该文件并重新启动]
EOF

Well, for step 1 and 2 isn't there a tomcat manager web interface; you could script that with curl or zsh with the libwww plug in.

For SSH you're looking to:
1) not get prompted for a password (use keys)
2) pass the command(s) on SSH's commandline, this is similar to rsh in a trusted network.

Other posts have shown you what to do, and I'd probably use sh too but I'd be tempted to use perl like ssh tomcatuser@server perl -e 'do-everything-on-one-line;' or you could do this:

either scp the_package.tbz tomcatuser@server:the_place/.
ssh tomcatuser@server /bin/sh <<\EOF
define stuff like TOMCAT_WEBAPPS=/usr/local/share/tomcat/webapps
tar xj the_package.tbz or rsync rsync://repository/the_package_place
mv $TOMCAT_WEBAPPS/old_war $TOMCAT_WEBAPPS/old_war.old
mv $THE_PLACE/new_war $TOMCAT_WEBAPPS/new_war
touch $TOMCAT_WEBAPPS/new_war [you don't normally have to restart tomcat]
mv $THE_PLACE/vhost_file $APACHE_VHOST_DIR/vhost_file
$APACHECTL restart [might need to login as apache user to move that file and restart]
EOF

爱*していゐ 2024-07-15 12:44:31

您需要 DSH 或分布式 shell,它在集群中经常使用。 这是链接: dsh

您基本上有节点组(其中包含节点列表的文件)并且您指定要在哪个节点组上运行命令,然后您将使用 dsh,就像使用 ssh 在它们上运行命令一样。

dsh -a /path/to/some/command/or/script

它将同时在所有计算机上运行该命令并返回带有主机名前缀的输出。 命令或脚本必须存在于系统上,因此共享 NFS 目录对于此类事情很有用。

You want DSH or distributed shell, which is used in clusters a lot. Here is the link: dsh

You basically have node groups (a file with lists of nodes in them) and you specify which node group you wish to run commands on then you would use dsh, like you would ssh to run commands on them.

dsh -a /path/to/some/command/or/script

It will run the command on all the machines at the same time and return the output prefixed with the hostname. The command or script has to be present on the system, so a shared NFS directory can be useful for these sorts of things.

起风了 2024-07-15 12:44:31

创建所有访问的机器的主机名 ssh 命令。
通过奎拉蒂
http://pastebin.com/pddEQWq2

#Use in .bashrc
#Use "HashKnownHosts no" in ~/.ssh/config or /etc/ssh/ssh_config 
# If known_hosts is encrypted and delete known_hosts

[ ! -d ~/bin ] && mkdir ~/bin
for host in `cut -d, -f1 ~/.ssh/known_hosts|cut -f1 -d " "`;
  do
    [ ! -s ~/bin/$host ] && echo ssh $host '$*' > ~/bin/$host
done
[ -d ~/bin ] && chmod -R 700 ~/bin
export PATH=$PATH:~/bin 

前执行:

$for i in hostname{1..10}; do $i who;done

Creates hostname ssh command of all machines accessed.
by Quierati
http://pastebin.com/pddEQWq2

#Use in .bashrc
#Use "HashKnownHosts no" in ~/.ssh/config or /etc/ssh/ssh_config 
# If known_hosts is encrypted and delete known_hosts

[ ! -d ~/bin ] && mkdir ~/bin
for host in `cut -d, -f1 ~/.ssh/known_hosts|cut -f1 -d " "`;
  do
    [ ! -s ~/bin/$host ] && echo ssh $host '$*' > ~/bin/$host
done
[ -d ~/bin ] && chmod -R 700 ~/bin
export PATH=$PATH:~/bin 

Ex Execute:

$for i in hostname{1..10}; do $i who;done
坦然微笑 2024-07-15 12:44:31

有一个名为 FLATT(灵活的自动化和故障排除工具) 的工具,它允许您使用以下命令在多个 Unix/Linux 主机上执行脚本:单击按钮。 它是一个在 Mac 和 Windows 上运行的桌面 GUI 应用程序,但也有一个命令行 java 客户端。
您可以创建批处理作业并在多个主机上重复使用。
需要 Java 1.6 或更高版本。

There is a tool called FLATT (FLexible Automation and Troubleshooting Tool) that allows you to execute scripts on multiple Unix/Linux hosts with a click of a button. It is a desktop GUI app that runs on Mac and Windows but there is also a command line java client.
You can create batch jobs and reuse on multiple hosts.
Requires Java 1.6 or higher.

丢了幸福的猪 2024-07-15 12:44:31

虽然这是一个复杂的主题,但我强烈推荐 Capistrano

Although it's a complex topic, I can highly recommend Capistrano.

英雄似剑 2024-07-15 12:44:31

我不确定此方法是否适用于您想要的所有内容,但您可以尝试如下操作:

$ cat your_script.sh | ssh your_host bash

这将在远程服务器上运行脚本(驻留在本地)。

I'm not sure if this method will work for everything that you want, but you can try something like this:

$ cat your_script.sh | ssh your_host bash

Which will run the script (which resides locally) on the remote server.

三岁铭 2024-07-15 12:44:31

只需阅读新的博客 使用setsid,除了主流内核之外,无需任何进一步的安装/配置。 在 Ubuntu14.04 下测试/验证。

虽然作者也有非常清晰的解释和示例代码,但以下是快速浏览的神奇部分:

#----------------------------------------------------------------------
# Create a temp script to echo the SSH password, used by SSH_ASKPASS
#----------------------------------------------------------------------
SSH_ASKPASS_SCRIPT=/tmp/ssh-askpass-script
cat > ${SSH_ASKPASS_SCRIPT} <<EOL
#!/bin/bash
echo "${PASS}"
EOL
chmod u+x ${SSH_ASKPASS_SCRIPT}

# Tell SSH to read in the output of the provided script as the password.
# We still have to use setsid to eliminate access to a terminal and thus avoid
# it ignoring this and asking for a password.
export SSH_ASKPASS=${SSH_ASKPASS_SCRIPT}
......
......
# Log in to the remote server and run the above command.
# The use of setsid is a part of the machinations to stop ssh 
# prompting for a password.
setsid ssh ${SSH_OPTIONS} ${USER}@${SERVER} "ls -rlt"

Just read a new blog using setsid without any further installation/configuration besides the mainstream kernel. Tested/Verified under Ubuntu14.04.

While the author has a very clear explanation and sample code as well, here's the magic part for a quick glance:

#----------------------------------------------------------------------
# Create a temp script to echo the SSH password, used by SSH_ASKPASS
#----------------------------------------------------------------------
SSH_ASKPASS_SCRIPT=/tmp/ssh-askpass-script
cat > ${SSH_ASKPASS_SCRIPT} <<EOL
#!/bin/bash
echo "${PASS}"
EOL
chmod u+x ${SSH_ASKPASS_SCRIPT}

# Tell SSH to read in the output of the provided script as the password.
# We still have to use setsid to eliminate access to a terminal and thus avoid
# it ignoring this and asking for a password.
export SSH_ASKPASS=${SSH_ASKPASS_SCRIPT}
......
......
# Log in to the remote server and run the above command.
# The use of setsid is a part of the machinations to stop ssh 
# prompting for a password.
setsid ssh ${SSH_OPTIONS} ${USER}@${SERVER} "ls -rlt"
赠我空喜 2024-07-15 12:44:31

我发现无需安装或配置太多软件的最简单方法是使用普通的旧 tmux。 假设您有 9 台 Linux 服务器。 选择一个盒子作为你的主要盒子。 启动 tmux 会话:

tmux

然后通过执行 8 次创建 9 个分割的 tmux 窗格:

ctrl-b + %

在此处输入图像描述

现在通过 SSH 连接到每个窗格中的每个框。 您需要了解一些 tmux 快捷方式。 要导航,请按:

ctrl+b <arrow-keys>

登录到每个窗格上的所有框后。 现在打开窗格同步,它可以让您在每个框中输入相同的内容:

ctrl+b :setw synchronize-panes on

现在,当您按任意键时,它将显示在每个窗格上。 要关闭它,只需将其打开即可。 要循环调整窗格大小,请按 ctrl+b <; 空格键>。

这对我来说效果更好,因为我需要查看每个终端输出,因为有时服务器在下载或升级软件时会因某种原因崩溃或挂起。 任何问题,您都可以单独隔离和解决。

Easiest way I found without installing or configuring much software is using plain old tmux. Say you have 9 linux servers. Pick a box as your main. Start a tmux session:

tmux

Then create 9 split tmux panes by doing this 8 times:

ctrl-b + %

enter image description here

Now SSH into each box in each pane. You'll need to know some tmux shortcuts. To navigate, press:

ctrl+b <arrow-keys>

Once your logged in to all your boxes on each pane. Now turn on pane synchronization where it lets you type the same thing into each box:

ctrl+b :setw synchronize-panes on

now when you press any keys, it will show up on every pane. to turn it off, just make on to off. to cycle resize panes, press ctrl+b < space-bar >.

This works alot better for me since I need to see each terminal output as sometimes servers crash or hang for whatever reason when downloading or upgrade software. Any issues, you can just isolate and resolve individually.

北方的巷 2024-07-15 12:44:30

您可以运行本地脚本,如 che 和 Yang 所示,和/或您可以使用此处文档:

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 

You can run a local script as shown by che and Yang, and/or you can use a Here document:

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 
你与清晨阳光 2024-07-15 12:44:30

通常,我只会使用 Expect 的原始 Tcl 版本。 您只需要在本地计算机上安装它即可。 如果我在使用 Perl 的程序中,我会使用 Net::SSH:: 执行此操作期待。 其他语言也有类似的“期望”工具。

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.

×眷恋的温暖 2024-07-15 12:44:30

前几天,Perl 邮件列表中出现了如何在许多服务器上同时运行命令的问题,我将给出相同的建议 我给了那里,就是使用gsh

http://outflux.net/unix/software/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 ~]$

您还可以使用 web+db 或 web-RHEL4 等来合并或拆分 Ghost 组。

我还要提到,虽然我从未使用过 shmux,但其网站包含一个软件列表(包括gsh),让您可以同时在许多服务器上运行命令。 Capistrano 已经被提及,(据我所知)也可能在该列表中。

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:

http://outflux.net/unix/software/gsh

gsh is similar to the "for box in box1_name box2_name box3_name" solution already given but 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.

[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.

I'll also mention that while I have never used shmux, its website contains a list of software (including gsh) that lets you run commands on many servers at once. Capistrano has already been mentioned and (from what I understand) could be on that list as well.

暮光沉寂 2024-07-15 12:44:30

看一下 Expect (manexpect)

我过去使用 Expect 完成过类似的任务。

Take a look at Expect (man expect)

I've accomplished similar tasks in the past using Expect.

や莫失莫忘 2024-07-15 12:44:30

您可以将本地脚本通过管道传输到远程服务器并使用一个命令执行它:

ssh -t user@host 'sh' < path_to_script

这可以通过使用公钥身份验证并使用脚本包装来执行并行执行来进一步自动化。

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.

蓝天 2024-07-15 12:44:30

您可以尝试paramiko。 这是一个纯Python ssh 客户端。 您可以对 ssh 会话进行编程。 无需在远程计算机上安装任何内容。

请参阅这篇关于如何用它。

You can try paramiko. It's a pure-python ssh client. You can program your ssh sessions. Nothing to install on remote machines.

See this great article on how to use it.

三人与歌 2024-07-15 12:44:30

为您提供结构,无需实际代码。

  1. 使用 scp 将安装/设置脚本复制到目标框。
  2. 使用 ssh 调用远程机器上的脚本。

To give you the structure, without actual code.

  1. Use scp to copy your install/setup script to the target box.
  2. Use ssh to invoke your script on the remote box.
如梦初醒的夏天 2024-07-15 12:44:30

pssh 可能很有趣,因为与此处提到的大多数解决方案不同,这些命令是并行运行的。

(为了我自己的使用,我编写了一个更简单的小脚本,与 GavinCattell 的脚本非常相似,它是 此处记录 - 用法语)。

pssh may be interesting since, unlike most solutions mentioned here, the commands are run in parallel.

(For my own use, I wrote a simpler small script very similar to GavinCattell's one, it is documented here - in french).

别在捏我脸啦 2024-07-15 12:44:30

您是否看过 PuppetCfengine. 他们可以做你想做的事,甚至可能更多。

Have you looked at things like Puppet or Cfengine. They can do what you want and probably much more.

善良天后 2024-07-15 12:44:30

对于那些偶然发现这个问题的人,我将提供一个使用 Fabric 的答案,它完全解决了上述问题:通过 ssh 在多个主机上执行任意命令。

安装 Fabric 后,您将创建一个 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")

然后,在本地计算机上运行 fab reloadsudo /etc/init.d/ apache2 reload 命令将在 env.hosts 中指定的所有主机上运行。

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.

Once fabric is installed, you'd create a fabfile.py, and implement tasks that can be run on your remote hosts. For example, a task to Reload Apache might look like this:

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.

不弃不离 2024-07-15 12:44:30

您可以按照以前的方式进行操作,只需编写脚本即可,而无需手动执行。 以下代码远程到名为“loca”的机器并在那里运行两个命令。 您需要做的只是插入您想要运行的命令。

che@ovecka ~ $ ssh loca 'uname -a; echo something_else'
Linux loca 2.6.25.9 #1 (blahblahblah)
something_else

然后,要遍历所有计算机,请执行以下操作:

for box in box1_name box2_name box3_name
do
   ssh $box 'commmands_to_run_everywhere'
done

为了使 ssh 功能无需一直输入密码即可工作,您需要设置密钥身份验证。 您可以在 IBM Developerworks 上阅读相关内容。

You can do it the same way you did before, just script it instead of doing it manually. The following code remotes to machine named 'loca' and runs two commands there. What you need to do is simply insert commands you want to run there.

che@ovecka ~ $ ssh loca 'uname -a; echo something_else'
Linux loca 2.6.25.9 #1 (blahblahblah)
something_else

Then, to iterate through all the machines, do something like:

for box in box1_name box2_name box3_name
do
   ssh $box 'commmands_to_run_everywhere'
done

In order to make this ssh thing work without entering passwords all the time, you'll need to set up key authentication. You can read about it at IBM developerworks.

゛时过境迁 2024-07-15 12:44:30

您可以使用 集群 ssh。 该链接指向 Debian package of the day 博客上关于集群 ssh 的讨论。

You can run the same command on several servers at once with a tool like cluster ssh. The link is to a discussion of cluster ssh on the Debian package of the day blog.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文