代码之家  ›  专栏  ›  技术社区  ›  f4nt

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

  •  18
  • f4nt  · 技术社区  · 16 年前

    我在周围搜索了一些类似的问题,但是除了运行一个命令或者可能有一些带有如下项目的命令之外:

    ssh user@host -t sudo su -
    

    但是,如果我基本上需要同时在15个服务器上运行一个脚本,该怎么办?这在巴什是可行的吗?在一个完美的世界里,如果可能的话,我需要避免安装应用程序。为了便于讨论,让我们假设我需要跨10个主机执行以下操作:

    1. 部署新的Tomcat容器
    2. 在容器中部署应用程序,并对其进行配置
    3. 配置Apache vhost
    4. 重载Apache

    我有一个脚本可以完成所有这些工作,但它依赖于我登录到所有服务器,从repo中提取一个脚本,然后运行它。如果这在bash中不可行,您建议什么替代方案?我是否需要一个更大的锤子,比如Perl(由于yum/up2date的存在,我可以保证在RHEL环境中所有盒子上都有python,所以可能首选python)?如果有人能向我指出任何有用的信息,我会非常感激,特别是如果它在bash中是可行的。我会选择Perl或Python,但我不太了解它们(正在研究)。谢谢!

    21 回复  |  直到 7 年前
        1
  •  9
  •   brian d foy    16 年前

    通常,我只使用Expect的原始TCL版本。你只需要把它放在本地机器上。如果我在使用Perl的程序中,我用 Net::SSH::Expect . 其他语言也有类似的“预期”工具。

        2
  •  11
  •   Bash    16 年前

    您可以运行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 
    
        3
  •  9
  •   rogerdpack    7 年前

    前几天,关于如何在许多服务器上同时运行命令的问题出现在一个Perl邮件列表上,我将给出同样的建议。 I gave there ,使用 gsh :

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

    GSH类似于 for box in box1_name box2_name box3_name “解决方案” already given 但我觉得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组合或拆分重影组。

    我也会提到,虽然我从未使用过shmux, its website 包含一个软件列表(包括GSH),允许您同时在多个服务器上运行命令。 Capistrano 已经被提到了,而且(据我所知)也可能在名单上。

        4
  •  6
  •   antik    16 年前

    看看Expect( man expect )

    我以前用expect完成过类似的任务。

        5
  •  4
  •   Yang Zhao    16 年前

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

    ssh -t user@host 'sh' < path_to_script
    

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

        6
  •  4
  •   Christopher Mahan    15 年前

    你可以试试 paramiko . 它是纯python ssh客户机。您可以对ssh会话进行编程。远程计算机上没有要安装的内容。

    看到这个 great article 关于如何使用它。

        7
  •  3
  •   Darron    16 年前

    给你一个没有实际代码的结构。

    1. 使用scp将安装/安装脚本复制到目标框。
    2. 使用ssh在远程框中调用脚本。
        8
  •  2
  •   bortzmeyer    16 年前

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

    (为了我自己的目的,我写了一个简单的小剧本,非常类似于加文卡特的剧本,它是 documented here - in french )

        9
  •  2
  •   Keltia    16 年前

    你看过像这样的东西吗 Puppet Cfengine . 他们可以做你想做的事,也许还有更多。

        10
  •  2
  •   Brad Montgomery    13 年前

    对于那些偶然发现这个问题的人,我将包括一个使用 Fabric 这正好解决了上面描述的问题:通过ssh在多个主机上运行任意命令。

    一旦安装了结构,您将创建一个 fabfile.py 实现 任务 可以在远程主机上运行。例如,任务 重载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 .

        11
  •  1
  •   che    16 年前

    您可以像以前那样做,只需编写脚本而不是手动执行即可。以下代码远程访问名为“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 .

        12
  •  1
  •   David Locke    16 年前

    您可以使用类似的工具在多个服务器上同时运行相同的命令 cluster ssh . 链接指向day blog的debian包上集群ssh的讨论。

        13
  •  1
  •   dlamblin    16 年前

    好吧,对于步骤1和2,没有Tomcat管理器Web界面;您可以用curl或zsh和libwww插件编写这个脚本。

    对于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

        14
  •  1
  •   Steve Baker    16 年前

    您需要DSH或分布式shell,这在集群中被大量使用。链接如下: dsh

    基本上,您有节点组(一个包含节点列表的文件),并指定希望在哪个节点组上运行命令,然后使用DSH,就像使用ssh在这些节点组上运行命令一样。

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

    它将同时在所有机器上运行该命令,并返回以主机名为前缀的输出。命令或脚本必须存在于系统中,因此共享的NFS目录对于这些事情可能很有用。

        15
  •  1
  •   Quierati    13 年前

    创建所有访问的计算机的主机名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
    
        16
  •  1
  •   Aliaksandr Belik Kanglai    11 年前

    有一个工具叫做 FLATT (FLexible Automation and Troubleshooting Tool) 这允许您通过单击按钮在多个UNIX/Linux主机上执行脚本。它是在Mac和Windows上运行的桌面GUI应用程序,但也有一个命令行Java客户端。
    您可以创建批处理作业并在多个主机上重用。
    要求Java 1.6或更高。

        17
  •  1
  •   André Laszlo    10 年前

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

        18
  •  0
  •   Jeremy Cantrell    16 年前

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

    $ cat your_script.sh | ssh your_host bash
    

    它将在远程服务器上运行脚本(位于本地)。

        19
  •  0
  •   gideon    12 年前

    Multixterm 这样做很酷,可以让你很容易地将1从n机器中按顺序放回。

        20
  •  0
  •   user3438301    11 年前

    刚刚读了一个新的 blog 使用 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"
    
        21
  •  -2
  •   GavinCattell    16 年前

    下面是在多台计算机上执行ssh命令的脚本,它可能有助于:

    #!/bin/bash
    MACHINES="machine1 machine2 machine3 machine4 machine5 machine6"
    for m in $MACHINES
    do
            cmd="ssh $m '$*'"
            eval $cmd
    done
    

    你甚至可以把它放在你的路径中,称它为类似sshall的东西,然后输入sshall命令。