并行执行ssh命令工具pssh
在维护集群时,常常需要在大量服务器上执行相同的命令,虽然可以自己写循环执行脚本,但是不仅麻烦而且执行效率不高。此时我们通常会使用pssh工具来并发执行SSH指令。
pssh是早期在Python 2上开发的工具,最早开源在google code上,后来代码库搬迁到github robinbowes/pssh 不过已经很久没有更新了(最后更新是2012年),甚至在 pssh · PyPI 也没有说明这个软件包在Python 3上运行是存在兼容问题的。不过,Github上 lilydjwg/pssh 提供了兼容Python 3的修正。
安装pssh
Ubuntu/debain 安装pssh
在Ubuntu上, pssh
包安装之后,直接执行 pssh
命令会提示无法找到指令。实际上Ubuntu安装 pssh
软件包后实际的执行程序是采用了 parallel-
开头的命令,例如 parallel-ssh
和 parallel-scp
等。所以,为了方便使用,可以建立软链接:
以下在Ubuntu上实践都直接使用
pssh
和pscp
等命令,如果你在Ubuntu上看不到这个指令(并且已经安装好pssh
软件包),可以尝试先通过软链接修正。
arch linux 安装pssh
arch的软件包仓库没有提供pssh,但是可以通过 pssh AUR package 安装:
Fedora安装pssh
CentOS安装mpssh
CentOS可以使用EPEL安装pssh,但是现在(CentOS 8)只提供MPSSH(Mass Parallel Secure Shell)来并发执行SSH。
使用方法和pssh类似,但是没有提供 -A
参数,也就是只能使用密钥认证,无法使用密码认证。这个问题我主要通过复用ssh连接方式解决,即在 ~/.ssh/config
中添加配置:
然后执行一次循环ssh登陆建立连接:
之后就可以通过 mpssh
并发执行ssh命令。
OpenSUSE
通过pip安装(推荐使用这个通用方法安装)
pssh实际上是一个python程序,所以可以通过 Python pip方式安装。通过pip安装可以用于Python 2环境通用,而且,通过Python virtualenv方式,可以自主在个人用户目录下安装,非常方便。
我在Python 3的virtualenv中通过pip安装了pssh之后,执行报错
参考 pssh的安装和问题 改为使用 Python 2的virtualenv环境就可以解决。
命令说明
命令
说明
pssh
并行在多个远程主机上执行ssh命令
pscp
并行从多个主机上复制文件
prsync
并行从多个主机使用rsync同步文件
pnuke
并行在多个主机上杀死进程
pslurp
并行在多个主机上复制文件到一个中心主机上
使用pssh指令
首先创建一个hosts文件,名字可以按需设置,例如,我要访问ceph集群,则创建
ceph-hosts
配置文件,内容如下
如果SSH端口不同,可以在主机ip后面加上端口号,例如 172.18.0.11:2222
表示该主机的SSH访问端口是 2222
常用参数
参数
说明
-h
主机名列表文件
-l
登陆用户名,例如 -l root
-A
提供统一的登陆密码
-i
交互模式,远程服务器的命令执行结果会输出
举例:
忽略服务器密钥
在批量处理主机时,如果需要每个服务器都确认服务器密钥是不现实的,这里就需要使用ssh的一个参数 -O StrictHostKeyChecking=no
,这个参数也可以传递给pssh
忽略错误密码
对于部分主机密码错误,我们希望直接跳过错误密码的节点,可以使用ssh的批处理模式 BatchMode=yes
,可以配置在用户的 ~/.ssh/config
中,这样执行pssh命令可以直接忽略错误密码的节点。
终端tty
在pssh执行 sudo
命令时候,会出现报错:
这个报错在ssh远程执行sudo命令时候也会遇到,原因是远程执行强制的基于screen的程序时,需要使用-t
参数来分配一个tty,即使ssh没有本地tty。不过,我没有找到如何把这个参数传递给pssh的方法,所以遇到这个问题,我暂时使用循环方式使用ssh命令。举例:
这里远程服务器sudo需要输入密码,采用了 sudo工具 中通过管道向sudo传输密码的方法,此时 sudo 需要使用参数
-S
从stdin
获取密码。
并发
pssh和pscp支持并发,但是在macOS上并发执行,例如 -p 100
则出现报错
我修订成 -p 10
能够缓解,但是多次运行脚本依然出现问题。参考 OSError: [Errno 35] Resource temporarily unavailable 这个问题和macOS的默认文件句柄数量限制有关。解决方法是放宽限制:
不过,需要重新登陆一次(或者关闭iterm终端,重新启动一次iterm)。但是,似乎并没有完全解决这个问题,退出iterm2,重新启动后再次执行脚本完成。似乎是资源释放问题。
使用ssh密钥登陆
对于使用SSH密钥的登陆方式,需要使用参数 -x
来使用扩展ssh参数指定密钥登陆,举例:
也可以在 ~/.ssh/config
指定扩展参数,例如
不过,最好的方法还是采用 keychain 来解决密钥认证,实际上就不需要使用
-x
参数来扩展。
对于密码保护的密钥
对于密码保护的密钥,建议使用 keychain 来解决密码输入
然后执行 pssh 指令就不再需要输入密钥保护密码了。
建议在 ~/.bashrc
中添加以下内容,则每次终端登陆就只要输入一次密钥保护密码就可以
应该也可以使用 SSH密钥认证:ssh-agent 来实现一次输入保护密码的密钥认证
参考
Last updated