主程序
#!/usr/bin/env python
# Time : 2020-8-11 13:25
# Author : fockrock
# Email : fockrock@126.com
# File : main.py
# Software: PyCharm
import settings
import paramiko
import threading
import os
class Hosts(threading.Thread):
# 定义远程主机的类
def __init__(self, host, port, username, password, cmd):
super(Hosts, self).__init__()
self.host = host
self.port = port
self.username = username
self.password = password
self.cmd = cmd
def run(self):
'''启动线程连接远程主机'''
cmd_command = self.cmd.split()[0] # 获取命令
if hasattr(self, cmd_command): # 类里有这个方法
getattr(self, cmd_command)() # 执行方法
else:
setattr(self, cmd_command, self.command) # 没有方法,映射command方法
getattr(self, cmd_command)() # 调用command方法
def command(self):
'''批量命令处理'''
ssh = paramiko.SSHClient() # 创建ssh对象
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy) # 允许连接不在konw_host文件里的主机
# 连接主机
ssh.connect(hostname=self.host, port=self.port, username=self.username, password=self.password)
stdin, stdout, stderr = ssh.exec_command(self.cmd) # 返回标准输入、输出及错误信息
res, err = stdout.read(), stderr.read()
result = res if res else err # 有命令执行结果,返回结果,没有打印错误信息
print("%s".center(50, '-') % self.host)
print(result.decode())
ssh.close()
def put(self):
'''文件上传方法'''
filemame = self.cmd.split()[1] # 获取文件名
transport = paramiko.Transport((self.host, self.port)) # 创建ssh实例
transport.connect(username=self.username, password=self.password) # 连接远程主机
sftp = paramiko.SFTPClient.from_transport(transport) # 创建ftp对象
try:
sftp.put(filemame, "/tmp/fockrock/%s" % filemame) # 文件上传到fockrock目录
print("%s 上传成功" % self.port)
except Exception as e:
print(e)
transport.close()
def get(self):
'''文件下载方法'''
filemame = self.cmd.split()[1]
transport = paramiko.Transport((self.host, self.port))
transport.connect(username=self.username, password=self.password)
sftp = paramiko.SFTPClient.from_transport(transport)
try:
sftp.get("/tmp/fockrock/%s" % filemame, filemame)
print("%s 下载成功" % self.port)
except Exception as e:
print(e)
transport.close()
def show_host_list():
"""显示主机分组、主机名及IP"""
for key in settings.remote_host_dic: # 打印分组及主机数
print(key, len(settings.remote_host_dic[key]))
while True:
choose_host_group = input("请选择主机分组:>>>").strip()
choice_dic = settings.remote_host_dic.get(choose_host_group)
if choice_dic:
for key in choice_dic: # 选择的分组存在,打印主机名及IP地址
print(key, choice_dic[key]['IP'])
return choice_dic
else:
print("没有这个主机组,请重新输入")
def start_thread(choice_dic):
"""为选择的分组所有主机单独开启一个线程"""
thread_list = []
while True:
cmd = input(">>>").strip()
if cmd:
for key in choice_dic: # 获取远程主机地址、端口、用户名、密码
host, port, username, password = choice_dic[key]["IP"], choice_dic[key]["port"], choice_dic[key]["username"], choice_dic[key]["password"]
func = Hosts(host, port, username, password, cmd) # 创建主机类
func.run() # 启动线程
for t in thread_list:
t.join()
else:
continue
if __name__ == '__main__':
choice_dic = show_host_list()
start_thread(choice_dic)
存储主机分组的文件
remote_host_dic = {
"group1": { #分组1
"h1": {"IP": "192.168.1.3", "username": "root", "password": "123456", "port": 22},
"h2": {"IP": "192.168.1.4", "username": "root", "password": "123456", "port": 22},
"h3": {"IP": "192.168.1.5", "username": "root", "password": "123456", "port": 22},
"h4": {"IP": "192.168.1.6", "username": "root", "password": "123456", "port": 22},
},
"group2": { #分组2
"h1": {"IP": "192.168.2.1", "username": "root", "password": "aaa", "port": 22},
"h2": {"IP": "192.168.2.2", "username": "root", "password": "bbb", "port": 22},
"h3": {"IP": "192.168.2.3", "username": "root", "password": "ccc", "port": 22},
"h4": {"IP": "192.168.2.4", "username": "root", "password": "ddd", "port": 22},
}
}
# print(remote_host_dic.get('group1'))
测试
1. 启动程序,打印主机分组和主机数
2. 输入group3,显示分组3的所有主机
3. 首先测试执行命令
1.5和1.6没有fockrock目录
创建目录再再执行cd命令
同时执行两个命令
4. 测试文件传输