【问题标题】:write a shell script to ssh to a remote machine and execute commands编写一个shell脚本ssh到远程机器并执行命令
【发布时间】:2012-12-05 08:56:39
【问题描述】:

我有两个问题:

  1. 有多个远程 linux 机器,我需要编写一个 shell 脚本,在每台机器上执行相同的命令集。 (包括一些 sudo 操作)。如何使用 shell 脚本来做到这一点?
  2. ssh到远程机器时,提示RSA指纹认证时如何处理。

远程机器是运行时创建的虚拟机,我只有它们的 IP。所以,我不能事先在这些机器中放置一个脚本文件并从我的机器上执行它们。

【问题讨论】:

  • 我想在远程 Linux 机器上部署一个类似代理的程序,它通过网络套接字(或 SSL)连接/通过定期轮询服务器来保持与服务器的连接。
  • 一组命令只需要执行一次,不需要维护连接
  • “没有脚本”的意思是“根本没有文件”,我想?您如何处理身份验证?您可以禁用主机指纹检查(请参阅我的答案),但如果您尚未设置公钥/私钥,您仍然会收到交互式密码提示。
  • 安德烈亚斯:是的。根本没有文件。 passwd 提示可以使用expect 处理为 `expect "?assword:" `

标签: linux shell ssh


【解决方案1】:

你可以按照这个方法:

  • 使用 Expect Script 连接到远程计算机。如果您的机器不支持期望,您可以下载相同的。编写 Expect 脚本非常简单(谷歌可以得到帮助)
  • 将所有需要在远程服务器上执行的操作放在一个 shell 脚本中。
  • 登录成功后,从期望脚本调用远程 shell 脚本。

【讨论】:

  • 正如我在问题中提到的,远程机器是在运行中创建的,我不能事先在机器中放置任何脚本。
  • 在这种情况下,将所有操作放在 Expect 脚本中。 Expect 脚本也可以在远程主机上运行命令。
【解决方案2】:

有多个远程 linux 机器,我需要编写一个 shell 脚本,它将在每台机器上执行相同的命令集。 (包括一些 sudo 操作)。使用 shell 脚本如何做到这一点?

你可以使用 ssh 来做到这一点,例如:

#!/bin/bash
USERNAME=someUser
HOSTS="host1 host2 host3"
SCRIPT="pwd; ls"
for HOSTNAME in ${HOSTS} ; do
    ssh -l ${USERNAME} ${HOSTNAME} "${SCRIPT}"
done

ssh到远程机器时,提示进行RSA指纹认证时如何处理。

您可以在 ssh 中添加StrictHostKeyChecking=no 选项:

ssh -o StrictHostKeyChecking=no -l username hostname "pwd; ls"

这将disable the host key check 并自动将主机密钥添加到已知主机列表中。如果您不想将主机添加到已知主机文件中,请添加选项-o UserKnownHostsFile=/dev/null

请注意,这会禁用某些安全检查,例如防止中间人攻击。因此,它不应该应用在安全敏感的环境中。

【讨论】:

  • 脚本语言是什么?你当然也可以从任何 shell 脚本调用ssh
  • 如果您还想执行 CTRL+C 并继续 ssh 到多个服务器怎么办?例如,在某些服务器中要求输入密码,而在另一些服务器中则没有,因此脚本会卡在那里。有没有一种类似于 -o 的方法来执行 CTRL c 或 CTRL d?
  • 密码在哪里?
【解决方案3】:

有很多方法可以处理这个问题。

我最喜欢的方法是在远程系统上安装http://pamsshagentauth.sourceforge.net/ 以及您自己的公钥。 (想办法把这些安装在虚拟机上,不知何故你安装了整个 Unix 系统,还有什么文件?)

转发您的 ssh 代理后,您现在无需密码即可登录每个系统。

更好的是,该 pam 模块将使用您的 ssh 密钥对对 sudo 进行身份验证,因此您可以根据需要使用 root(或任何其他用户)权限运行。

您无需担心主机密钥交互。如果输入不是终端,那么 ssh 只会限制您转发代理和使用密码进行身份验证的能力。

您还应该查看软件包 like Capistrano. 一定要环顾该网站;它介绍了远程脚本。

各个脚本行可能如下所示:

ssh remote-system-name command arguments ... # so, for exmaple,
ssh target.mycorp.net sudo puppet apply

【讨论】:

    【解决方案4】:

    如果您能够编写 Perl 代码,那么您应该考虑使用Net::OpenSSH::Parallel

    您将能够以声明的方式描述必须在每个主机中运行的操作,并且该模块将处理所有可怕的细节。还支持通过sudo 运行命令。

    【讨论】:

      【解决方案5】:

      使用 apt-get install sshpass 安装 sshpass,然后编辑脚本并按相应顺序放置您的 linux 机器 IP、用户名和密码。之后运行该脚本。而已 !此脚本将在所有系统中安装 VLC。

      #!/bin/bash
      SCRIPT="cd Desktop; pwd;  echo -e 'PASSWORD' | sudo -S apt-get install vlc"
      HOSTS=("192.168.1.121" "192.168.1.122" "192.168.1.123")
      USERNAMES=("username1" "username2" "username3")
      PASSWORDS=("password1" "password2" "password3")
      for i in ${!HOSTS[*]} ; do
           echo ${HOSTS[i]}
           SCR=${SCRIPT/PASSWORD/${PASSWORDS[i]}}
           sshpass -p ${PASSWORDS[i]} ssh -l ${USERNAMES[i]} ${HOSTS[i]} "${SCR}"
      done
      

      【讨论】:

      • 使用 $SSHPASS 导出密码以避免在脚本中显示。参考:tecmint.com/…
      【解决方案6】:

      对于这类任务,我反复使用 Ansible,它允许在多个容器或 VM 中连贯地复制 bash 脚本。 Ansible(更准确地说是 Red Hat)现在有一个额外的 Web 界面 AWX,这是他们的商业 Tower 的开源版本。

      Ansible:https://www.ansible.com/
      AWX:https://github.com/ansible/awx
      Ansible Tower:商业产品,你可能会首先探索免费的开源 AWX,而不是 Tower 的 15 天免费试用

      【讨论】:

        【解决方案7】:

        这对我有用。

        语法:ssh -i pemfile.pem user_name@ip_address 'command_1;命令2;命令 3'

        #! /bin/bash
        
        echo "########### connecting to server and run commands in sequence ###########"
        ssh -i ~/.ssh/ec2_instance.pem ubuntu@ip_address 'touch a.txt; touch b.txt; sudo systemctl status tomcat.service'
        

        【讨论】:

        • 我希望在远程机器上执行一个命令,这个示例脚本在同一行的 ssh 命令之后使用远程命令提供了帮助。谢谢。
        【解决方案8】:

        有多种方法可以在多台远程 Linux 机器上执行命令或脚本。 一种简单且最简单的方法是通过 pssh(并行 ssh 程序)

        pssh:是一种用于在多个主机上并行执行 ssh 的程序。它提供了诸如向所有进程发送输入、向 ssh 传递密码、将输出保存到文件以及超时等功能。

        示例和用法:

        连接到 host1 和 host2,并分别打印“hello, world”:

         pssh -i -H "host1 host2" echo "hello, world"
        

        通过脚本在多台服务器上运行命令:

        pssh -h hosts.txt -P -I<./commands.sh
        

        在不检查或保存主机密钥的情况下使用和运行命令:

        pssh -h hostname_ip.txt -x '-q -o StrictHostKeyChecking=no -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes' -i  'uptime; hostname -f'
        

        如果文件 hosts.txt 有大量条目,比如 100,那么也可以将并行度选项设置为 100 以确保命令同时运行:

        pssh -i -h hosts.txt -p 100 -t 0 sleep 10000
        

        选项
        -I:读取输入并发送到每个 ssh 进程。
        -P: 告诉 pssh 在输出到达时显示输出。
        -h: 读取主机的文件。
        -H : [user@]host[:port] 用于单主机。
        -i: 在每个主机完成时显示标准输出和标准错误
        -x args: 传递额外的 SSH 命令行参数
        -o 选项: 可用于以配置文件中使用的格式给出选项。(/etc/ssh/ssh_config) (~/.ssh/config)
        -p 并行度: 使用给定的数量作为最大并发连接数
        -q 安静模式: 导致大多数警告和诊断消息被抑制。
        -t: 在给定的秒数后使连接超时。 0 表示 pssh 不会使任何连接超时

        ssh到远程机器时,提示输入时如何处理 RSA指纹认证。

        禁用 StrictHostKeyChecking 以处理 RSA 身份验证提示。
        -o StrictHostKeyChecking=no

        来源:man pssh

        【讨论】:

          【解决方案9】:

          这对我有用。我做了一个函数。把它放在你的 shell 脚本中:

          sshcmd(){
              ssh $1@$2 $3
          }
          
          sshcmd USER HOST COMMAND
          

          如果您有多台机器要执行相同的命令,您可以用分号重复该行。例如,如果你有两台机器,你会这样做:

          sshcmd USER HOST COMMAND ; sshcmd USER HOST COMMAND
          

          将 USER 替换为计算机的用户。将 HOST 替换为计算机的名称。将 COMMAND 替换为您要在计算机上执行的命令。

          希望这会有所帮助!

          【讨论】:

            【解决方案10】:

            接受的答案依次发送给机器。如果您想ssh 到多台机器并同时在它们上运行一些长时间运行的命令,例如scp,请将ssh 命令作为后台进程运行。

            #!/bin/bash
            username="user"
            servers=("srv-001" "srv-002" "srv-002" "srv-003");
            script="pwd;"
            for s in "${servers[@]}"; do
                echo "sshing ${username}@${s} to run ${script}"
                (ssh ${username}@${s} ${script})& # Run in background
            done
            wait # If removed, you can run some other script here
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-04-26
              • 1970-01-01
              • 2012-06-24
              • 2016-03-07
              • 2018-03-29
              • 2016-03-28
              • 2012-07-27
              相关资源
              最近更新 更多