一、簡介
paramiko是一個基于SSH用于連接遠程服務器并執行相關操作(SSHClient和SFTPClinet,即一個是遠程連接,一個是上傳下載服務),使用該模塊可以對遠程服務器進行命令或檔案操作,值得一說的是,fabric和ansible內部的遠程管理就是使用的paramiko來現實,
二、使用
1、下載
pip3 install paramiko
2、模塊使用
SSHClient:
遠程連接分為兩種:(1)基于用戶名密碼連接 (2)基于公鑰秘鑰連接
通過是用paramiko遠程操作,其實本質也分為兩種:(1)只用SSHClient (2)自己創建一個transport
(1)基于用戶名和密碼的連接
import paramiko # 創建SSH物件 ssh = paramiko.SSHClient() # 允許連接不在know_hosts檔案中的主機 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 連接服務器 ssh.connect(hostname='c1.salt.com', port=22, username='GSuser', password='123') # 執行命令 stdin, stdout, stderr = ssh.exec_command('ls') # 獲取命令結果 result = stdout.read() # 關閉連接 ssh.close()
SSHClient 封裝 Transport
import paramiko transport = paramiko.Transport(('hostname', 22)) transport.connect(username='GSuser', password='123') ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df') print(stdout.read()) transport.close()
(2)基于公鑰秘鑰連接
import paramiko # 添加公鑰密鑰檔案 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') # 創建SSH物件 ssh = paramiko.SSHClient() # 允許連接不在know_hosts檔案中的主機 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 連接服務器 ssh.connect(hostname='192.168.1.105', port=22, username='666', key=private_key) # 執行命令 # 執行多條命令時需要將各個命令用‘;’隔開,最后將get_pty設為True;如果是單條命令的則只傳入命令即可 stdin, stdout, stderr = ssh.exec_command('cd dw/2020-06-02/;ls',get_pty=True) # 多條命令的話會將執行結果一起回傳,所以建議遍歷列印,也可以直接列印:print(stdout.read().decode('utf-8')) files = stdout.readlines() for i in files: # 列印執行反饋結果 print(i.encode().decode('utf-8').split()[0]) # 列印報錯資訊 print(stderr.read().decode('utf-8')) # 關閉連接 ssh.close()
SSHClient 封裝Transport
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') transport = paramiko.Transport(('192.168.1.105', 22)) transport.connect(username='666', pkey=private_key) ssh = paramiko.SSHClient() ssh._transport = transport # 執行多條命令時需要將各個命令用‘;’隔開,最后將get_pty設為True;如果是單條命令的則只傳入命令即可 stdin, stdout, stderr = ssh.exec_command('cd dw/2020-06-02/;ls',get_pty=True) # 多條命令的話會將執行結果一起回傳,所以建議遍歷列印,也可以直接列印:print(stdout.read().decode('utf-8')) files = stdout.readlines() for i in files: # 列印執行反饋結果 print(i.encode().decode('utf-8').split()[0]) # 列印報錯資訊 print(stderr.read().decode('utf-8')) transport.close()
SFTPClient:
用于連接遠程服務器并進行上傳下載功能,
(1)基于用戶名密碼上傳下載
import paramiko transport = paramiko.Transport(('192.168.1.105',22)) transport.connect(username='666',password='123') sftp = paramiko.SFTPClient.from_transport(transport) # 將location.py 上傳至服務器 /tmp/test.py sftp.put('/tmp/location.py', '/tmp/test.py') # 將remove_path 下載到本地 local_path sftp.get('remove_path', 'local_path') transport.close()
(2)基于公鑰秘鑰上傳下載
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') transport = paramiko.Transport(('192.168.1.105', 22)) transport.connect(username='666', pkey=private_key ) sftp = paramiko.SFTPClient.from_transport(transport) # 將location.py 上傳至服務器 /tmp/test.py sftp.put('/tmp/location.py', '/tmp/test.py') # 將remove_path 下載到本地 local_path sftp.get('remove_path', 'local_path') transport.close()
Demo: 實作遠程命令執行和檔案上傳
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko class SSHConnection(object): def __init__(self, host='192.168.12.68', port=22, username='locojoy',pwd='123321QQ!'): self.host = host self.port = port self.username = username self.pwd = pwd self.__k = None def run(self): self.connect() # 連接遠程服務器 self.upload('db.py','/tmp/1.py') # 將本地的db.py檔案上傳到遠端服務器的/tmp/目錄下并改名為1.py self.cmd('df') # 執行df 命令 self.close() # 關閉連接 def connect(self): transport = paramiko.Transport((self.host, self.port)) transport.connect(username=self.username, password=self.pwd) self.__transport = transport def close(self): self.__transport.close() def upload(self,local_path,target_path): sftp = paramiko.SFTPClient.from_transport(self.__transport) sftp.put(local_path,target_path) def cmd(self, command): ssh = paramiko.SSHClient() ssh._transport = self.__transport # 執行命令 stdin, stdout, stderr = ssh.exec_command(command) # 獲取命令結果 result = stdout.read() print(result) return result obj = SSHConnection() obj.run()
paramiko在堡壘機中的應用
(1)簡單實體:遠程連接一臺主機,操作命令,linux版本,輸入終端為回車則發送命令,不支持tab補全功能,
import paramiko, sys, os, socket, select, getpass from paramiko.py3compat import u # 在python3中是這樣使用的,如果在Python2中則注釋這行 # 這個程式依賴于終端,只能在Liunx下運行,windows用其他的方式 tran = paramiko.Transport(('192.168.12.68', 22,)) tran.start_client() tran.auth_password('locojoy', '123321QQ!') # 打開一個通道 chan = tran.open_session() # 獲取一個終端 chan.get_pty() # 激活器 chan.invoke_shell() # 原始的方法利用終端進行收發訊息 # 利用sys.stdin,肆意妄為執行操作 # 用戶在終端輸入內容,并將內容發送至遠程服務器 # 遠程服務器執行命令,并將結果回傳 # 用戶終端顯示內容 while True: # 監視用戶輸入和服務器回傳資料 # sys.stdin 處理用戶輸入 # chan 是之前創建的通道,用于接收服務器回傳資訊 # 通過select監聽終端(輸入輸出),一旦變化,就將拿到的資料發送給服務器 # 通過監聽socket句柄,如果有變化表示服務器要給我發訊息 readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) # 通過select.select 監聽chan(打開的通道(和遠程服務器連接的狀態)), sys.stdin(輸入),一旦變化就寫入readable # 當chan變化時,加入到readable,遠程服務器發送內容過來 if chan in readable: try: x = u(chan.recv(1024)) # Python3用這個 # x = chan.recv(1024) Python2使用這個 if len(x) == 0: print('\r\n*** EOF\r\n') break sys.stdout.write(x) # 寫入緩沖區 sys.stdout.flush() # 重繪,將緩沖區內容顯示出來 except socket.timeout: pass # 當sys.stdin 放入readable中時,將獲取到的內容發送到遠程服務器 if sys.stdin in readable: inp = sys.stdin.readline() chan.sendall(inp) chan.close() tran.close()
(2)每按一個鍵就發送記錄,并支持tab自動補全
import paramiko, sys, os, socket, select, getpass, termios, tty from paramiko.py3compat import u tran = paramiko.Transport(('10.211.55.4', 22,)) tran.start_client() tran.auth_password('wupeiqi', '123') # 打開一個通道 chan = tran.open_session() # 獲取一個終端 chan.get_pty() # 激活器 chan.invoke_shell() # 獲取原tty屬性 oldtty = termios.tcgetattr(sys.stdin) try: # 為tty設定新屬性 # 默認當前tty設備屬性: # 輸入一行回車,執行 # CTRL+C 行程退出,遇到特殊字符,特殊處理, # 這是為原始模式,不認識所有特殊符號 # 放置特殊字符應用在當前終端,如此設定,將所有的用戶輸入均發送到遠程服務器 tty.setraw(sys.stdin.fileno()) # 恢復終端原始狀態,每按一個鍵就發送 chan.settimeout(0.0) while True: # 監視 用戶輸入 和 遠程服務器回傳資料(socket) # 阻塞,直到句柄可讀 r, w, e = select.select([chan, sys.stdin], [], [], 1) if chan in r: # 獲取服務回傳的內容 try: x = u(chan.recv(1024)) if len(x) == 0: print('\r\n*** EOF\r\n') break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r: # 發送命令 x = sys.stdin.read(1) # 讀取一個字符 if len(x) == 0: break chan.send(x) # 發送一個字符 finally: # 重新設定終端屬性,將終端狀態還原 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) chan.close() tran.close()
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/140467.html
標籤:Python
