zoukankan      html  css  js  c++  java
  • ssh无密码登录多台机器,并让所有远程机执行相同命令

    问题集锦

      其实标题的内容就是很常见的集群操作,当有一个脚本或者一个命令需要很多个机器同时(或者说接近同时)执行时,就涉及到几个问题:

    1.   怎么通知每个主机?
    2.   每个主机收到通知后,怎么让主机执行命令?
    3.   怎么让上面的过程同时发生?

      上面其实可以分为两步:

    1.   登录到单个机器
    2.   让单个机器执行命令

      重复上面的两个操作,执行多进程或者创建子进程都能达到目标。

      

      接下来的问题:

    1.   ssh登录需要密码,怎么设置无需密码就可以登录
    2.   登录后怎么让登录的机器执行命令

    ssh免密码登录

      关于这个问题,可以参考这篇博客ssh免密码登录配置

      大致的过程:  

      ServerA 的UserA用户 希望使用ServerB 中UserB的账号免密登录ServerB

    → ~ $  ssh-keygen -t rsa     
    #使用RSA加密算法生成密钥对
    
    → ~ $  ssh-copy-id  UserB@ServerB  
    #将自己生成的公钥复制到远程主机的authorized_keys文件上

      设置完成后,就可以在本地使用ssh UserB@ServerB来免密登录了。

    让远程机执行命令

      登录远程机之后,让远程机执行命令,在ServerB

      你可能你会说下面这个命令

    → ~ $  ssh UserB@ServerB && echo "hello world" > index
    

      然而上面这个命令并不会像我们期望的那样执行,过程如下:

    1.   在ServerA的终端执行上面这条命令
    2.   会先使用UserB免密登录到ServerB
    3.   接着会进入ServerB的终端
    4.   那条命令中的echo命令就被挂起了,因为ssh进程还没执行结束呢
    5.   在ServerB的终端中执行exit,退出ServerB
    6.   回到ServerA的终端,继续执行echo命令,然后命令执行结束

      查看ServerA中UserA的子目录,会多出一个index文件,但是ServerB中UserB的家目录中却不会有index文件。

      正确做法

    → ~ $  ssh UserB@ServerB  'echo "hello world" > index'
    

      没错,只是单纯的用引号将命令括起来就行了,这样会被当做位置参数传递给ssh,然后就能成功在远程机上运行了

    同时对多个机器发指令(多进程并行)

      Linux里面的多进程有一个特别方便的方法:在命令后面加一个&符号,那么该命令就会在后台执行,也就是多进程了。

      所以要有了前面几步基础之后,可以下面这样做,实现向所有机器同时发送指令:

    #!/bin/bash
    #多进程对多个机器同时发指令
    
    #注意下面的用户和ip是一一对应的,顺序不要搞错,额否则不能登录
    #user1登录server1
    server=(
        "192.168.1.1"
        "192.168.1.2"
        "192.168.1.3"
        "192.168.1.4"
    )
    user=(
        "test1"
        "test2"
        "test3"
        "test4"
    )
    
    #服务器和用户账号对应关系
    tot_s=${#server[*]}
    tot_u=${#user[*]}
    
    if [ $tot_s -ne $tot_u ];then
        echo "服务器和用户账号数量不对应,请检查server列表和user列表"
        exit
    fi
    
    i=0
    while [ $i -lt $tot_u ];do
        (ssh ${user[$i]}@${server[$i]} "command1;command2" & )  2>> ~/Desktop/log.txt
        #注意一定要在最后面加&符号,否则就是串行执行,不能体现并行。
        #将错误重定向到日志文件中
    
        if [ $? -ne 0 ];then
            echo "${user[$i]}@${server[$i]}执行过程中出现异常"
        fi
    
        #注意迭代器别忘了自增
        i=$[ $i + 1 ]
    done

      注意:前提是已经可以无密登录,否则每次连接都要输入密码。

  • 相关阅读:
    Java中线程池,你真的会用吗?ExecutorService ThreadPoolExcutor
    springcloud中微服务的优雅停机(已验证)
    SpringCloud eureka
    Spring Boot实战:静态资源处理
    你真的理解CountDownLatch与CyclicBarrier使用场景吗?
    Effective.Java第56-66条(规范相关)
    Effective.Java第45-55条(规范相关)
    Effective.Java第34-44条(枚举)
    装饰(Decorator)模式
    合成(Composite)模式
  • 原文地址:https://www.cnblogs.com/-beyond/p/9267050.html
Copyright © 2011-2022 走看看