使⽤Pythonparamiko模块利⽤多线程实现ssh并发执⾏操
1.paramiko概述
ssh是⼀个协议,OpenSSH是其中⼀个开源实现,paramiko是Python的⼀个库,实现了SSHv2协议(底层使⽤cryptography)。
有了Paramiko以后,我们就可以在Python代码中直接使⽤SSH协议对远程服务器执⾏操作,⽽不是通过ssh命令对远程服务器进⾏操作。
由于paramiko属于第三⽅库,所以需要使⽤如下命令先⾏安装
2.安装paramiko
pip install paramiko
3.常⽤⽅法
connect():实现远程服务器的连接与认证,对于该⽅法只有hostname是必传参数。
常⽤参数
hostname 连接的⽬标主机
port=SSH_PORT 指定端⼝
username=None 验证的⽤户名
password=None 验证的⽤户密码
pkey=None 私钥⽅式⽤于⾝份验证
key_filename=None ⼀个⽂件名或⽂件列表,指定私钥⽂件
timeout=None 可选的tcp连接超时时间
allow_agent=True, 是否允许连接到ssh代理,默认为True 允许
look_for_keys=True 是否在~/.ssh中搜索私钥⽂件,默认为True 允许
compress=False, 是否打开压缩
set_missing_host_key_policy():设置远程服务器没有在know_hosts⽂件中记录时的应对策略。⽬前⽀持三种策略:python安装教程非常详细
设置连接的远程主机没有本地主机密钥或HostKeys对象时的策略,⽬前⽀持三种:
AutoAddPolicy ⾃动添加主机名及主机密钥到本地HostKeys对象,不依赖load_system_host_key的配置。即新建⽴ssh连接时不需要再输⼊yes或no进⾏确认
WarningPolicy ⽤于记录⼀个未知的主机密钥的python警告。并接受,功能上和AutoAddPolicy类似,但是会提⽰是新连接RejectPolicy ⾃动拒绝未知的主机名和密钥,依赖load_system_host_key的配置。此为默认选项
exec_command():在远程服务器执⾏Linux命令的⽅法。
如  exec_command("ls /")  exec_command("df -h")
4.使⽤⽅法
import paramiko
# 实例化SSHClient
client = paramiko.SSHClient()
# ⾃动添加策略,保存服务器的主机名和密钥信息,如果不添加,那么不再本地know_hosts⽂件中记录的主机将⽆法连接
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接SSH服务端,以⽤户名和密码进⾏认证
# 打开⼀个Channel并执⾏命令
stdin, stdout, stderr = _command('df -h ') # stdout 为正确输出,stderr为错误输出,同时是有1个变量有值
# 打印执⾏结果
ad().decode('utf-8'))
# 关闭SSHClient
client.close()
5.利⽤多线程实现ssh并发访问
要求:
编写⼀个remote_comm.py脚本,实现以下功能:
在⽂件中取出所有远程主机IP地址
在shell命令⾏中接受远程服务器IP地址⽂件、远程服务器密码以及在远程主机上执⾏的命令
通过多线程实现在所有的远程服务器上并发执⾏命令
步骤⼀:编写脚本
#!/usr/bin/env python3
import sys
import getpass
import paramiko
import threading
import os
#创建函数实现远程连接主机、服务器密码以及在远程主机上执⾏的命令的功能
def remote_comm(host, pwd, command):
#创建⽤于连接ssh服务器的实例
ssh = paramiko.SSHClient()
#设置⾃动添加主机密钥
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#连接ssh服务器,添加连接的主机、⽤户名、密码填好,捕获异常,有异常则跳出函数
try:
except:
return
#在ssh服务器上执⾏指定命令,返回3项类⽂件对象,分别是,输⼊、输出、错误
stdin, stdout, stderr = _command(command)
#读取输出
out = ad()
#读取错误
error = ad()
#如果有输出
if out:
#打印主机输出内容
print('[%s] OUT:\n%s' % (host, out.decode('utf8')))
#如果有错误
if error:
#打印主机错误信息
print('[%s] ERROR:\n%s' % (host, error.decode('utf8')))
#程序结束
ssh.close()
if __name__ == '__main__':
#设定sys.argv长度,确保remote_comm函数中参数数量
if len(sys.argv) != 3:
print('Usage: %s ipaddr_file "command"' % sys.argv[0])
exit(1)
#判断命令⾏上输⼊如果不是⽂件,确保输⼊的是⽂件
if not os.path.isfile(sys.argv[1]):
print('No such file:', sys.argv[1])
exit(2)
#fname为存储远程主机ip的⽂件,⽤sys.argv⽅法,可以在执⾏脚本时再输⼊⽂件名,更为灵活
fname = sys.argv[1]
#command为在远程主机上执⾏的命令,⽤sys.argv⽅法,可以在执⾏脚本时再输⼊相应命令,command为remote_comm函数第三个参数  command = sys.argv[2]
#通过getpass输⼊远程服务器密码,pwd为remote_comm函数第⼆个参数
# pwd = pass()
pwd='Taren1.bgsn'
#打开存有远程主机ip的⽂件
with open(fname) as fobj:
#将遍历⽂件将ip以列表形式存⼊ips,line.strip()可以去掉每⾏ip后\n
ips = [line.strip() for line in fobj]
#循环遍历列表,获取ip地址,ip为remote_comm函数第⼀个参数
for ip in ips:
#将读取到的ip地址作为remote_comm函数实际参数传递给函数,ips中有⼏个ip地址循环⼏次
#创建多线程
t = threading.Thread(target=remote_comm, args=(ip, pwd, command))
#启⽤多线程
t.start()
步骤⼆:编写ssh名单
创建⼀个⽂件,输⼊某个⽹段所有可以ping通的ip,可以先⽤nmap出活跃主机扫描,或者⾃⼰编写⼀个python脚本
[root@room9pc01 ~]#nmap -n -sP 176.130.7.0/24 | grep 176 | awk '{print $5}' > /mnt/
[root@room9pc01 ~]#cat /mnt/
Nmap scan report for 176.130.7.1
Nmap scan report for 176.130.7.24
Nmap scan report for 176.130.7.46
Nmap scan report for 176.130.7.53
Nmap scan report for 176.130.7.57
.....................
步骤三:执⾏脚本
执⾏脚本,此脚本有两个参数,⼀个是⽂件参数,⼀个是执⾏命令
[root@room9pc01 mnt]# python3 ssh.py 'who'
[176.130.7.57] OUT:
student :0      2019-12-02 09:04 (:0)
student pts/0    2019-12-02 15:03 (:0)
[176.130.7.169] OUT:
student :0      2019-12-02 08:17 (:0)
student pts/0    2019-12-02 08:23 (:0)
student pts/4    2019-12-02 08:24 (:0)
[176.130.7.162] OUT:
student :0      2019-12-02 08:17 (:0)
student pts/0    2019-12-02 15:03 (:0)
[176.130.7.178] OUT:
student :0      2019-12-02 08:06 (:0)
总结
以上所述是⼩编给⼤家介绍的使⽤Python paramiko模块利⽤多线程实现ssh并发执⾏操作,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。在此也⾮常感谢⼤家对⽹站的⽀持!
如果你觉得本⽂对你有帮助,欢迎转载,烦请注明出处,谢谢!