使用 shell 在多服务器上批量操做

需求


平常工做中,咱们常须要同时在多台服务器上执行一样的命令,如对比日志、检查服务等。这就须要咱们有服务器批量操做的能力。html

两年前写过一篇文章,shell实现SSH自动登录 使用 shell 的 expect 命令进行 ssh 登录,这种方式的灵活性确实很是高,但实现起来比较麻烦,并且单进程阻塞的特性也是它的硬伤,若是使用它进行批量操做,就须要启动多个 expect 进程,涉及到各个进程和主进程的双向通讯,处理起来很是麻烦。python

不过咱们能够借用 ssh 公钥登录 的能力,方便地实如今多个服务器上批量执行命令。git

转载随意,文章会持续修订,请注明来源地址:https://zhenbianshu.github.io 。github

SSH 协议


说公钥登录以前,先来讲一下 SSH 协议。算法

SSH 是一种网络协议,咱们常说的 ssh 通常指其实现,即 OpenSSH,在 shell 中,也就是 ssh 命令。shell

SSH

Secure Shell(安全外壳协议,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。 SSH经过在网络中创建安全隧道来实现SSH客户端与服务器之间的链接。安全

SSH 的原理跟 HTTPS 差很少,都是基于 TCP 和 非对称加密进行的应用层协议。它跟 HTTPS 的不一样之处在于 HTTPS 经过 数字证书 和 数字证书认证中心 来防止中间人攻击,而 ssh 服务器的公钥没有人公证,只能经过其公钥指纹来人工肯定其身份。服务器

以下图所示,咱们第一次使用 ssh 登录某台服务器时, ssh 会提示咱们验证服务器的公钥指纹。网络

当咱们验证此公钥指纹是咱们要登录的服务器后,服务器的公钥会被添加到 ~/.ssh/known_hosts 里,再登录时,ssh 检测到是已认证服务器后就会跳过公钥验证阶段。运维

建连过程

关于通讯加密的概念,我在以前的文章也有所介绍,参见:再谈加密-RSA非对称加密的理解和使用。至于 SSH 协议的建连过程,则能够参阅:Protocol Basics: Secure Shell Protocol 

总结起来主要包括如下步骤:

  • TCP 三次握手
  • SSH 协议版本协商
  • 客户端与服务端的公钥交换
  • 加密算法协商
  • 客户端使用对称加密的密钥认证
  • 客户端与服务端安全通讯

我使用 tcpdump + wireshark 抓包并查看了一下其 SSH 的建连过程,以下图所示:

不得再也不次感叹 tcpdump + wireshark 是学习网络协议的真神器。

ssh 工具


ssh

做为工具, ssh 分为服务端和客户端,在服务端,它是 sshd,通常占用 22 端口。咱们日常使用的是其客户端,通常用法为 ssh user@host,而后根据 ssh 的提示,咱们输入密码后登录到服务器。

它的功能很是强大,看其支持参数就知道了。

ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] [user@]hostname [command] 

介绍完了 SSH 协议和 ssh 命令,终于说到公钥登录了。

公钥登录

理解了非对称加密的原理后,再公钥登录会很是简单。因为公私钥是惟一的一对,在客户端保障本身私钥安全的状况下,服务端经过公钥就能够彻底肯定客户端的真实性,因此要实现公钥登录,咱们就要先生成一个公私密钥对。

经过 ssh-keygen 命令来生成密钥对,为了让步骤更完整,我把它们暂时保存到工做目录,默认会保存到 ~/.ssh 目录。

~ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/zbs/.ssh/id_rsa): ./test Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in ./test. Your public key has been saved in ./test.pub. The key fingerprint is: SHA256:xxxxx/B17z/xxxxxx zbs@zbs.local The key's randomart image is: +---[RSA 2048]----+ | o+*.. EO* | | .... | | oo+ .o++.o| +----[SHA256]-----+ ~ ls ./test* ./test ./test.pub 

把私钥文件 ./test 的内容放到 客户端的 ~/.ssh/id_rsa,再使用密码试登录到服务器后,将公钥内容 ./test.pub 里的内容放到 服务器的 ~/.ssh/authorized_keys

再次登录时,ssh 会自动使用本身的私钥来认证,也就避免了输出密码。

批量操做

公钥登录帮咱们避免了每次登录服务器要输出密码的麻烦,它同时也解决了每一个登录会话都会同步阻塞的问题,这样咱们就能够利用 ssh 的 ssh user@host command 方式来直接在服务器上执行命令。

同时,在咱们拥有一个 ip 列表的状况下,使用 for 循环遍历 ip 列表,在多个服务器上批量执行命令也就成为了可能。

关于批量执行,已经有不少开源工具了,如使用 python 编写的 pssh,C++ 编写的 hss(帮同事作个广告)等。

多服务器文件合并


前几天,帮同事在多个服务器上查找日志,须要把在多个服务器上查到的日志都汇总到同一台机器上进行统计分析。我是用 pssh 登录的多个服务器,因为日志量太大,查出来的结果输出到终端上再复制有些不现实,而使用重定向,结果又会重定向到各自的服务器。

scp

这时候可使用 scp,scp 跟 ssh 是同一家族的命令,也是基于 SSH 协议实现的安全传输协议。只要在各个服务器之间互相保存着对方的公钥,就能够跟 ssh 命令同样,实现免密操做。

scp 的常见用法是 scp src dst,其中远程路径能够表示为 user@host:/path。在批量登录的状况下,可使用 grep 等命令先把结果文件输入到一个文件中,再使用 scp 命令将其复制到同一台服务器。

为了不各个服务器的文件名冲突,可使用 uuidgen | xargs -I {} scp result.log root@ip:/result/{} 将各个服务器的结果复制到不一样的文件中,再使用 cat 将 result 文件夹中的文件合并到一块。

nc

固然,大多数状况下,咱们的服务器之间并不会互相保存公钥,不过 nc 命令能够完美解决这个问题。

nc 的 -k 选项,可让 nc 服务端在文件传输结束后保持链接不关闭。这样,咱们使用 nc -k -4l port > result.log 启动一个 nc 服务端,再使用 grep xxx info.log | nc ip port 便可实现结果数据的合并。

小结


本文介绍的各个工具仍是属于开发的小打小闹,了解多一些工具老是好的。若是作运维工做的话,仍是须要依赖 OPS 平台集成更多功能,实现完整的自动化。

关于本文有什么疑问能够在下面留言交流,若是您以为本文对您有帮助,欢迎关注个人 微博 或 GitHub 。您也能够在个人 博客REPO 右上角点击 Watch 并选择 Releases only 项来 订阅 个人博客,有新文章发布会第一时间通知您。

相关文章
相关标签/搜索