今天做了一个很简单的小项目,感受到了 paramiko 模块的强大,也深感自己 Linux 的功力不行~~
需求很少,我就简单地说下:
1. 主机分组可以配置文件实现 (我用字典存数据的).
2. 登陆功能不做。选择分组后可查看组内对应主机的主机名和 IP 地址.
3. >>>cmd: df(输入命令则起多个线程 (视组内有多少个主机而定) 同时执行)
输出:
-------------h1------------
……(命令返回的数据)
-------------h2------------
……
>>>put test.yy(本地文件) filename (把本地的 test.yy 文件传到远程主机的 / root 目录下)
4. 可写在配置文件中。包括远程主机的: 主机名 IP 用户名 密码 端口
流程图
我做的流程图
目录结构:
from_windows.py(待上传的文件)
main.py(批量主机管理接口)
View Code
- 1 """批量主机管理接口"""
- 2
- 3 import core
- 4
- 5 if __name__ == "__main__":
- 6 core.run()
core.py(核心代码,被接口调用)
- 1 """核心代码"""
- 2 import settings
- 3 import paramiko
- 4 import threading
- 5 import os
- 6
- 7
- 8 class REMOTE_HOST(object):
- 9 #远程操作主机
- 10 def __init__(self, host, port ,username, password, cmd):
- 11 self.host = host
- 12 self.port = port
- 13 self.username = username
- 14 self.password = password
- 15 self.cmd = cmd
- 16
- 17 def run(self):
- 18 """起线程连接远程主机后调用"""
- 19 cmd_str = self.cmd.split()[0]
- 20 if hasattr(self, cmd_str): #反射 eg:调用put方法
- 21 getattr(self, cmd_str)()
- 22 else:
- 23 #setattr(x,'y',v)is equivalent to ``x.y=v''
- 24 setattr(self, cmd_str, self.command)
- 25 getattr(self, cmd_str)() #调用command方法,执行批量命令处理
- 26
- 27 def command(self):
- 28 """批量命令处理"""
- 29 ssh = paramiko.SSHClient() #创建ssh对象
- 30 #允许连接不在know_hosts文件中的主机
- 31 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- 32 ssh.connect(hostname=self.host,port=self.port,username=self.username,password=self.password)
- 33 stdin,stdout,stderr = ssh.exec_command(self.cmd)
- 34 result = stdout.read()
- 35 print("%s".center(50, "-") % self.host)
- 36 print(result.decode())
- 37 ssh.close()
- 38
- 39 def put(self):
- 40 """上传文件"""
- 41 filename = self.cmd.split()[1] #要上传的文件
- 42 transport = paramiko.Transport((self.host, self.port))
- 43 transport.connect(username=self.username, password=self.password)
- 44 sftp = paramiko.SFTPClient.from_transport(transport)
- 45 sftp.put(filename, filename)
- 46 print("put sucesss")
- 47
- 48 transport.close()
- 49
- 50
- 51 def show_host_list():
- 52 """通过选择分组显示主机名与IP"""
- 53 for index, key in enumerate(settings.msg_dic):
- 54 print(index + 1, key, len(settings.msg_dic[key]))
- 55 while True:
- 56 choose_host_list = input(">>>(eg:group1)").strip()
- 57 host_dic = settings.msg_dic.get(choose_host_list)
- 58 if host_dic:
- 59 #print(host_dic)
- 60 for key in host_dic:
- 61 print(key, host_dic[key]["IP"])
- 62 return host_dic
- 63 else:
- 64 print("NO exit this group!")
- 65
- 66
- 67 def interactive(choose_host_list):
- 68 """根据选择的分组主机起多个线程进行批量交互"""
- 69 thread_list = []
- 70 while True:
- 71 cmd = input(">>>").strip()
- 72 if cmd:
- 73 for key in choose_host_list:
- 74 host, port, username, password = choose_host_list[key]["IP"], choose_host_list[key]["port"], \
- 75 choose_host_list[key]["username"], choose_host_list[key]["password"]
- 76 func = REMOTE_HOST(host, port, username, password, cmd) # 实例化类
- 77 t = threading.Thread(target=func.run) # 起线程
- 78 t.start()
- 79 thread_list.append(t)
- 80 for t in thread_list:
- 81 t.join() # 主线程等待子线程执行完毕
- 82 else:
- 83 continue
- 84
- 85
- 86 def run():
- 87 choose_host_list = show_host_list()
- 88 interactive(choose_host_list)
settings.py(配置文件)
View Code
- 1 """配置文件"""2 3 msg_dic = {
- 4 "group1": {#分组1 5 "h1": {
- "IP": "192.168.1.1",
- "username": "11",
- "password": "aa",
- "port": 22
- },
- 6 "h2": {
- "IP": "192.168.1.2",
- "username": "22",
- "password": "bb",
- "port": 22
- },
- 7 "h3": {
- "IP": "192.168.1.3",
- "username": "33",
- "password": "cc",
- "port": 22
- },
- 8 "h4": {
- "IP": "192.168.1.4",
- "username": "44",
- "password": "dd",
- "port": 22
- },
- 9 "h5": {
- "IP": "192.168.1.5",
- "username": "55",
- "password": "ee",
- "port": 22
- },
- 10 "h6": {
- "IP": "192.168.1.6",
- "username": "66",
- "password": "ff",
- "port": 22
- },
- 11
- },
- 12 13 "group2": {#分组2 14 "h1": {
- "IP": "192.168.2.1",
- "username": "111",
- "password": "aaa",
- "port": 22
- },
- 15 "h2": {
- "IP": "192.168.2.2",
- "username": "222",
- "password": "bbb",
- "port": 22
- },
- 16 "h3": {
- "IP": "192.168.2.3",
- "username": "333",
- "password": "ccc",
- "port": 22
- },
- 17 "h4": {
- "IP": "192.168.2.4",
- "username": "444",
- "password": "ddd",
- "port": 22
- },
- 18 "h5": {
- "IP": "192.168.2.5",
- "username": "555",
- "password": "eee",
- "port": 22
- },
- 19 "h6": {
- "IP": "192.168.2.6",
- "username": "666",
- "password": "fff",
- "port": 22
- },
- 20 "h7": {
- "IP": "192.168.2.7",
- "username": "777",
- "password": "ggg",
- "port": 22
- },
- 21 "h8": {
- "IP": "192.168.2.8",
- "username": "888",
- "password": "hhh",
- "port": 22
- },
- 22
- },
- 23 24 "group3": {
- 25 "h1": {
- "IP": "192.168.179.133",
- "username": "root",
- "password": "zcl",
- "port": 22
- },
- 26
- }
- 27
- }
测试:
硬件限制,我只用连接一台虚拟机测试~
- C:\Python34\python3.exe C:/Users/Administrator/PycharmProjects/laonanhai/host_manage/main.py
- 1 group1 6
- 2 group3 1
- 3 group2 8
- >>>(eg:group1)group3
- h1 192.168.179.133
- >>>put from_windows.py
- put sucesss
- >>>
- >>>ls
- ------------------------192.168.179.133------------------------
- anaconda-ks.cfg
- database_test
- from_windows.py
- install.log
- install.log.syslog
- m
- oot
- \root
- tmp\from_windows.py
- >>>
上传前没有 from_windows.py 文件,上传后就有了!
PS: 关于 paramiko 模块可以看看这篇博客
来源: