轉載☞:https://www.cnblogs.com/meng-wei-zhi/p/8258674.htmlhtml
參考☞:https://www.cnblogs.com/python-nameless/p/6855804.htmlpython
Python3之paramiko模塊
一. 簡介
paramiko是一個基於SSH用於鏈接遠程服務器並執行相關操做(SSHClient和SFTPClinet,即一個是遠程鏈接,一個是上傳下載服務),使用該模塊能夠對遠程服務器進行命令或文件操做,值得一說的是,fabric和ansible內部的遠程管理就是使用的paramiko來現實。linux
二. 使用
1. 下載安裝ios
pycrypto,因爲 paramiko 模塊內部依賴pycrypto,因此先下載安裝pycrypto pip3 install pycrypto pip3 install paramiko
2. 模塊使用shell
SSHClient:windows
遠程鏈接分爲兩種:(1)基於用戶名密碼鏈接 (2)基於公鑰祕鑰鏈接服務器
經過是用paramiko遠程操做,其實本質也分爲兩種:(1)只用SSHClient (2)本身建立一個transportsession
(1)基於用戶名和密碼的鏈接less
1 import paramiko 2 3 # 建立SSH對象 4 ssh = paramiko.SSHClient() 5 # 容許鏈接不在know_hosts文件中的主機 6 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 7 # 鏈接服務器 8 ssh.connect(hostname='c1.salt.com', port=22, username='GSuser', password='123') 9 # 執行命令 10 stdin, stdout, stderr = ssh.exec_command('ls') 11 # 獲取命令結果 12 result = stdout.read() 13 # 關閉鏈接 14 ssh.close()
SSHClient 封裝 Transportssh
1 import paramiko 2 3 transport = paramiko.Transport(('hostname', 22)) 4 transport.connect(username='GSuser', password='123') 5 6 ssh = paramiko.SSHClient() 7 ssh._transport = transport 8 9 stdin, stdout, stderr = ssh.exec_command('df') 10 print(stdout.read()) 11 12 transport.close()
(2)基於公鑰祕鑰鏈接
1 import paramiko 2 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 4 # 建立SSH對象 5 ssh = paramiko.SSHClient() 6 # 容許鏈接不在know_hosts文件中的主機 7 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 8 # 鏈接服務器 9 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key) 10 # 執行命令 11 stdin, stdout, stderr = ssh.exec_command('df') 12 # 獲取命令結果 13 result = stdout.read() 14 # 關閉鏈接 15 ssh.close()
SSHClient 封裝Transport
1 import paramiko 2 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 4 transport = paramiko.Transport(('hostname', 22)) 5 transport.connect(username='wupeiqi', pkey=private_key) 6 ssh = paramiko.SSHClient() 7 ssh._transport = transport 8 stdin, stdout, stderr = ssh.exec_command('df') 9 transport.close()
SFTPClient:
用於鏈接遠程服務器並進行上傳下載功能。
(1)基於用戶名密碼上傳下載
1 import paramiko 2 3 transport = paramiko.Transport(('hostname',22)) 4 transport.connect(username='GSuser',password='123') 5 6 sftp = paramiko.SFTPClient.from_transport(transport) 7 # 將location.py 上傳至服務器 /tmp/test.py 8 sftp.put('/tmp/location.py', '/tmp/test.py') 9 # 將remove_path 下載到本地 local_path 10 sftp.get('remove_path', 'local_path') 11 12 transport.close()
(2)基於公鑰祕鑰上傳下載
1 import paramiko 2 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 4 5 transport = paramiko.Transport(('hostname', 22)) 6 transport.connect(username='GSuser', pkey=private_key ) 7 8 sftp = paramiko.SFTPClient.from_transport(transport) 9 # 將location.py 上傳至服務器 /tmp/test.py 10 sftp.put('/tmp/location.py', '/tmp/test.py') 11 # 將remove_path 下載到本地 local_path 12 sftp.get('remove_path', 'local_path') 13 14 transport.close()
Demo: 實現遠程命令執行和文件上傳
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import paramiko 4 5 class SSHConnection(object): 6 7 def __init__(self, host='192.168.12.68', port=22, username='locojoy',pwd='123321QQ!'): 8 self.host = host 9 self.port = port 10 self.username = username 11 self.pwd = pwd 12 self.__k = None 13 14 def run(self): 15 self.connect() # 鏈接遠程服務器 16 self.upload('db.py','/tmp/1.py') # 將本地的db.py文件上傳到遠端服務器的/tmp/目錄下並更名爲1.py 17 self.cmd('df') # 執行df 命令 18 self.close() # 關閉鏈接 19 20 def connect(self): 21 transport = paramiko.Transport((self.host, self.port)) 22 transport.connect(username=self.username, password=self.pwd) 23 self.__transport = transport 24 25 def close(self): 26 self.__transport.close() 27 28 def upload(self,local_path,target_path): 29 sftp = paramiko.SFTPClient.from_transport(self.__transport) 30 sftp.put(local_path,target_path) 31 32 def cmd(self, command): 33 ssh = paramiko.SSHClient() 34 ssh._transport = self.__transport 35 # 執行命令 36 stdin, stdout, stderr = ssh.exec_command(command) 37 # 獲取命令結果 38 result = stdout.read() 39 print(result) 40 return result 41 42 obj = SSHConnection() 43 obj.run()
paramiko在堡壘機中的應用
(1)簡單實例:遠程鏈接一臺主機,操做命令,linux版本,輸入終端爲回車則發送命令。不支持tab補全功能。
1 import paramiko, sys, os, socket, select, getpass 2 from paramiko.py3compat import u # 在python3中是這樣使用的,若是在Python2中則註釋這行 3 4 # 這個程序依賴於終端,只能在Liunx下運行,windows用其餘的方式 5 6 tran = paramiko.Transport(('192.168.12.68', 22,)) 7 tran.start_client() 8 tran.auth_password('locojoy', '123321QQ!') 9 10 # 打開一個通道 11 chan = tran.open_session() 12 # 獲取一個終端 13 chan.get_pty() 14 # 激活器 15 chan.invoke_shell() 16 17 # 原始的方法利用終端進行收發消息 18 # 利用sys.stdin,肆意妄爲執行操做 19 # 用戶在終端輸入內容,並將內容發送至遠程服務器 20 # 遠程服務器執行命令,並將結果返回 21 # 用戶終端顯示內容 22 23 while True: 24 # 監視用戶輸入和服務器返回數據 25 # sys.stdin 處理用戶輸入 26 # chan 是以前建立的通道,用於接收服務器返回信息 27 # 經過select監聽終端(輸入輸出),一旦變化,就將拿到的數據發送給服務器 28 # 經過監聽socket句柄,若是有變化表示服務器要給我發消息 29 readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) 30 # 經過select.select 監聽chan(打開的通道(和遠程服務器鏈接的狀態)), sys.stdin(輸入),一旦變化就寫入readable 31 # 當chan變化時,加入到readable,遠程服務器發送內容過來 32 if chan in readable: 33 try: 34 x = u(chan.recv(1024)) # Python3用這個 35 # x = chan.recv(1024) Python2使用這個 36 if len(x) == 0: 37 print('\r\n*** EOF\r\n') 38 break 39 sys.stdout.write(x) # 寫入緩衝區 40 sys.stdout.flush() # 刷新,將緩衝區內容顯示出來 41 except socket.timeout: 42 pass 43 # 當sys.stdin 放入readable中時,將獲取到的內容發送到遠程服務器 44 if sys.stdin in readable: 45 inp = sys.stdin.readline() 46 chan.sendall(inp) 47 48 chan.close() 49 tran.close()
(2)每按一個鍵就發送記錄,並支持tab自動補全
1 import paramiko, sys, os, socket, select, getpass, termios, tty 2 from paramiko.py3compat import u 3 4 tran = paramiko.Transport(('10.211.55.4', 22,)) 5 tran.start_client() 6 tran.auth_password('wupeiqi', '123') 7 # 打開一個通道 8 chan = tran.open_session() 9 # 獲取一個終端 10 chan.get_pty() 11 # 激活器 12 chan.invoke_shell() 13 14 # 獲取原tty屬性 15 oldtty = termios.tcgetattr(sys.stdin) 16 try: 17 # 爲tty設置新屬性 18 # 默認當前tty設備屬性: 19 # 輸入一行回車,執行 20 # CTRL+C 進程退出,遇到特殊字符,特殊處理。 21 # 這是爲原始模式,不認識全部特殊符號 22 # 放置特殊字符應用在當前終端,如此設置,將全部的用戶輸入均發送到遠程服務器 23 tty.setraw(sys.stdin.fileno()) # 恢復終端原始狀態,每按一個鍵就發送 24 chan.settimeout(0.0) 25 26 while True: 27 # 監視 用戶輸入 和 遠程服務器返回數據(socket) 28 # 阻塞,直到句柄可讀 29 r, w, e = select.select([chan, sys.stdin], [], [], 1) 30 if chan in r: # 獲取服務返回的內容 31 try: 32 x = u(chan.recv(1024)) 33 if len(x) == 0: 34 print('\r\n*** EOF\r\n') 35 break 36 sys.stdout.write(x) 37 sys.stdout.flush() 38 except socket.timeout: 39 pass 40 if sys.stdin in r: # 發送命令 41 x = sys.stdin.read(1) # 讀取一個字符 42 if len(x) == 0: 43 break 44 chan.send(x) # 發送一個字符 45 46 finally: 47 # 從新設置終端屬性,將終端狀態還原 48 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) 49 50 chan.close() 51 tran.close()