如何通过SSH远程将命令自动运行到多个服务器并行?
题
我已经搜索了类似的问题,但除了运行一个命令或者一些命令,例如:
ssh user@host -t sudo su -
但是,如果我基本上需要同时运行一个脚本(比方说)15个服务器,该怎么办?这在bash中是可行的吗?在完美的世界中,我需要尽可能避免安装应用程序。为了论证,让我们说我需要在10个主机上执行以下操作:
- 部署新的Tomcat容器
- 在容器中部署应用程序并进行配置
- 配置Apache vhost
- 重新加载Apache 醇>
我有一个脚本可以完成所有这些,但它依赖于我登录所有服务器,从repo中拉下脚本,然后运行它。如果这在bash中不可行,你建议用什么替代方案?我是否需要更大的锤子,例如Perl(Python可能是首选,因为我可以保证在RHEL环境中的所有盒子上都有Python,这要归功于yum / up2date)?如果有人能够向我指出任何有用的信息,我将不胜感激,特别是如果它在bash中可行的话。我会满足于Perl或Python,但我只是不知道那些(继续)。谢谢!
解决方案
通常,我会使用Expect的原始Tcl版本。您只需要在本地计算机上拥有它。如果我在使用Perl的程序中,我使用 Net :: SSH ::期待。其他语言有类似的<!> quot; expect <!> quot;工具。
其他提示
你可以运行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
前几天在Perl邮件列表上出现了如何在多个服务器上运行命令的问题,我将给出相同的建议我给了那里,这是用gsh
:
http://outflux.net/unix/software/gsh
gsh类似于<!>“; for box in box1_name box2_name box3_name
<!>”;解决方案已经给出但我发现gsh更方便。您在web,db,RHEL4,x86_64或其他任何组(man ghosts)中设置包含服务器的/ etc / 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组合或拆分重影组。
我还要提到,虽然我从未使用过shmux,但其网站包含一个列表软件(包括gsh),允许您一次在多个服务器上运行命令。 Capistrano 已经被提及,并且(根据我的理解)也可以列在该列表中。
看一下Expect(man expect
)
我过去使用Expect完成了类似的任务。
您可以将本地脚本通过管道传输到远程服务器并使用以下命令执行它:
ssh -t user@host 'sh' < path_to_script
通过使用公钥认证和脚本包装来执行并行执行,可以进一步自动化。
为您提供结构,没有实际代码。
- 使用scp将安装/设置脚本复制到目标框。
- 使用ssh在远程控制台上调用脚本。 醇>
对于那些偶然发现这个问题的人,我将包含一个使用 Fabric 的答案,它可以解决所描述的问题上面:通过ssh在多个主机上运行任意命令。
安装完Fabric后,您将创建fabfile.py
,并实施可在远程主机上运行的任务。例如, Reload Apache 的任务可能如下所示:
from fabric.api import env, run
env.hosts = ['host1@example.com', 'host2@example.com']
def reload():
""" Reload Apache """
run("sudo /etc/init.d/apache2 reload")
然后,在本地计算机上运行fab reload
,sudo /etc/init.d/apache2 reload
命令将在env.hosts
中指定的所有主机上运行。
您可以像以前一样进行操作,只需编写脚本而不是手动执行。以下代码将远程命名为'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 上阅读相关内容。
您可以使用 cluster ssh 。该链接是关于当天博客的Debian软件包上的集群ssh的讨论。
嗯,对于第1步和第2步,没有tomcat管理器Web界面;你可以用libl插件用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/.
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
结果
您需要DSH或分布式shell,它在群集中使用很多。以下是链接: dsh
你基本上有节点组(一个包含节点列表的文件),你指定了你希望运行命令的节点组然后你会使用dsh,就像你在ssh上运行命令一样。
dsh -a /path/to/some/command/or/script
它将同时在所有计算机上运行该命令,并返回带有主机名前缀的输出。命令或脚本必须存在于系统中,因此共享NFS目录可用于这些类型的事情。
创建所有访问过的计算机的hostname ssh命令。 由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
有一个名为 FLATT(FLexible Automation and Troubleshooting Tool)的工具,允许您在多个Unix / Linux上执行脚本主机只需单击按钮即可。它是一个在Mac和Windows上运行的桌面GUI应用程序,但也有一个命令行java客户端 您可以创建批处理作业并在多个主机上重复使用 需要Java 1.6或更高版本。
虽然这是一个复杂的话题,但我强烈推荐 Capistrano 。
我不确定这种方法是否适用于您想要的所有内容,但您可以尝试这样的方法:
$ cat your_script.sh | ssh your_host bash
将运行远程服务器上的脚本(位于本地)。
Multixterm 这样做很酷,并且可以轻松地将n中的1个放入机器按顺序返回。
刚刚阅读新的博客除了主流内核之外,使用 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"
这是一个在多台机器上执行SSH命令的脚本,它可能有所帮助:
#!/bin/bash
MACHINES="machine1 machine2 machine3 machine4 machine5 machine6"
for m in $MACHINES
do
cmd="ssh $m '$*'"
eval $cmd
done
你甚至可以将它放在你的路径中,称之为sshAll,然后输入sshAll命令。