Python堡壘機實現之基礎知識python
通常的堡壘機必需要具有如下5個基本功能:mysql
一、權限控制 二、執行命令 三、上傳下載文件 四、遠程登陸 五、記錄操做
權限控制sql
說明:根據不一樣的登陸用戶分配不一樣的可管理的主機組。(再細分的權限就是根據不一樣的用戶控制可在主機上執行的命令,通常不會限制的這麼嚴格)shell
思路:使用數據庫建立用戶表,表字段有ID、用戶名、密碼、所屬組,再建立主機表,表字段有ID,主機IP,所屬組。其中用戶表中的所屬組和主機表中的所屬組相對應,這樣就能把兩張表關聯起來。當用戶登陸的時候就能夠根據用戶名去獲取可管理的主機列表。數據庫
例子:這裏只寫出關於python鏈接mysql數據庫的例子服務器
執行命令:session
說明:這裏的執行命令通常是指批量執行命令,好比須要同時獲取N臺主機的主機名。併發
思路:使用paramiko模塊來實現遠程登陸服務器並執行命令。使用multiprocessing來實現批量併發執行。ssh
例子:(這裏只寫出paramiko模塊遠程密碼登陸服務器並執行命令的例子)socket
import paramiko class Paramiko_Manage(): def __init__(self,host,port,user,passwd): #初始化鏈接服務器所須要的參數 self.host = host self.port = port self.user = user self.passwd = passwd #使用密碼認證 def connect(self): #鏈接方法,用來創建與服務器的鏈接 self.transport = paramiko.Transport((self.host,self.port)) self.transport.connect(username=self.user,password=self.passwd) print('connect') def close(self): #關閉方法,用來關閉與服務器的鏈接 self.transport.close() print('close') def cmd(self,command): #執行命令的方法,接收須要執行的命令做爲參數 ssh = paramiko.SSHClient() ssh._transport = self.transport stdin, stdout, stderr = ssh.exec_command(command,timeout=3) print('command resluat: ',stdout.read()) def run(self,command): self.connect() #創建鏈接 self.cmd(command) #執行命令 self.close() #關閉鏈接 p = Paramiko_Manage('192.168.100.20',22,'test','123456') p.run('hostname') # 執行結果: # connect # command resluat: Test1 # # close
上傳、下載文件:
說明:批量上傳文件相對比較簡單,若是是批量下載文件還須要考慮到多臺服務器文件重名的問題。
還須要考慮到文件上傳後比較大小以確認是否上傳下載成功。
思路:使用paramiko模塊來實現遠程上傳下載文件。使用multiprocessing來實現批量併發執行。
例子:(這裏只寫出paramiko模塊遠程祕鑰認證登陸服務器並執行命令的例子)
import paramiko import os class Paramiko_Manage(): def __init__(self,host,port,user,key): self.host = host self.port = port self.user = user keyfile = os.path.expanduser(key) #使用祕鑰認證 self.key = paramiko.RSAKey.from_private_key_file(keyfile) def connect(self): self.transport = paramiko.Transport((self.host,self.port)) self.transport.connect(username=self.user,pkey=self.key) print('connect') def close(self): self.transport.close() print('close') def trans(self,file1,file2): #傳輸文件的方法 sftp = paramiko.SFTPClient.from_transport(self.transport) file1 = '%s_%s' % (file1, self.host) #修改下載文件的保存文件名 sftp.get(file2,file1) file1_size = os.path.getsize(file1) #獲取下載文件的大小 file2_size = int(str(sftp.stat(file2)).split()[4]) #獲取遠程文件的大小 if file1_size == file2_size: #比較兩個文件大小 print('File trans done') def run(self,file1,file2): self.connect() #創建鏈接 self.trans(file1,file2) #傳輸文件 self.close() #關閉鏈接 p = Paramiko_Manage('192.168.100.20',22,'test2','~/.ssh/id_rsa') p.run('/root/hosts','/etc/hosts') # 執行結果: # connect # File trans done # close
遠程登陸和記錄操做:
說明:經過堡壘機ssh遠程鏈接到服務器,並執行操做,和在終端執行操做的效果同樣。
思路:使用paramiko實現遠程鏈接服務器的功能,使用sys.stdin和select處理用戶輸入和接受返回結果。
例子:
import paramiko import select import sys import socket import os tran = paramiko.Transport((host,port)) #鏈接服務器,host和port自定義 tran.start_client() default_path = os.path.join(os.environ['HOME'],'.ssh','id_rsa') key = paramiko.RSAKey.from_private_key_file(default_path) tran.auth_publickey('root',key) chan = tran.open_session() #打開一個通道 chan.get_pty() #獲取一個終端 chan.invoke_shell() #激活器 f = open('log.log','a') #打開一個文件用於寫入執行的操做 while True: # 監視用戶輸入和服務器返回數據 # sys.stdin 處理用戶輸入 # chan 是以前建立的通道,用於接收服務器返回信息 readable,writeable,error = select.select([chan,sys.stdin,],[],[],1) if chan in readable: #接受命令的返回結果 try: x = chan.recv(1024) if len(x) == 0: print('\r\n*** EOF\r\n',) f.close() #退出時關閉記錄文件 break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in readable: #處理用戶輸入發送到服務器執行 inp = sys.stdin.readline() f.write(inp) #記錄用戶輸入 chan.sendall(inp) chan.close() tran.close()