paramiko
該模塊基於SSH用於連接遠程服務器並執行相關操作
SSHClient
遠程連接服務器有兩種方法:SSHClient、tranceport
用於連接遠程服務器並執行基本命令
基於用戶名密碼連接:
1 import paramiko 2 # 創建SSH對象 3 ssh = paramiko.SSHClient() 4 # 允許連接不在know_hosts文件中的主機 5 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 6 # 連接服務器 7 ssh.connect(hostname='192.168.247.131', port=22, username='root', password='111111') 8 # 執行命令 9 stdin, stdout, stderr = ssh.exec_command('pwd') 10 # 獲取命令結果 11 result = stdout.read() 12 print(result) 13 # 關閉連接 14 ssh.close()
SSHClient封裝transport
1 import paramiko 2 3 transport = paramiko.Transport(('hostname', 22)) 4 transport.connect(username='wupeiqi', 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()
基於公鑰密鑰連接:
1 import paramiko 2 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 3 # 創建SSH對象 4 ssh = paramiko.SSHClient() 5 # 允許連接不在know_hosts文件中的主機 6 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 7 # 連接服務器 8 ssh.connect(hostname='192.168.247.131', port=22, username='root', key=private_key) 9 # 執行命令 10 stdin, stdout, stderr = ssh.exec_command('df') 11 # 獲取命令結果 12 result = stdout.read() 13 14 15 16 # 關閉連接 17 18 ssh.close()
封裝
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') transport = paramiko.Transport(('hostname', 22)) transport.connect(username='wupeiqi', pkey=private_key) ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df') transport.close()
SFTPClient
實現文件下載的方法:Tranceport
用於連接遠程服務器並執行上傳下載
基於用戶名密碼上傳下載
1 import paramiko 2 3 4 5 transport = paramiko.Transport(('hostname',22)) 6 7 transport.connect(username='wupeiqi',password='123') 8 9 10 11 sftp = paramiko.SFTPClient.from_transport(transport) 12 13 # 將location.py 上傳至服務器 /tmp/test.py 14 15 sftp.put('/tmp/location.py', '/tmp/test.py') 16 17 # 將remove_path 下載到本地 local_path 18 19 sftp.get('remove_path', 'local_path') 20 21 22 23 transport.close()
基於公鑰密鑰上傳下載
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') transport = paramiko.Transport(('hostname', 22)) transport.connect(username='wupeiqi', 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()
通過以上分析,可以知道,如果想實現遠程連接執行命令,只能使用tranceport方法。
通過利用transport和SSHClient實現在一次鏈接中多次執行命令和上傳、下載文件。
1 import paramiko 2 import uuid 3 class SSHConnection(object): 4 def __init__(self,host='192.168.247.131',port=22,username='root',pwd='111111'): 5 self.host = host 6 self.port = port 7 self.username = username 8 self.pwd = pwd 9 self._k = None 10 11 def run(self): 12 self.connect() 13 pass 14 self.close() 15 16 def connect(self): 17 transport = paramiko.Transport((self.host,self.port)) 18 transport.connect(username=self.username,password=self.pwd) 19 self.__transport = transport 20 def close(self): 21 self.__transport.close() 22 def cmd(self,command): 23 ssh = paramiko.SSHClient() 24 ssh._transport = self.__transport 25 stdin,stdout,stderr = ssh.exec_command(command) 26 result = stdout.read() 27 return result 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 create_file(self): 33 file_name = str(uuid.uuid4()) 34 with open(file_name, 'w') as f: 35 f.write('sb') 36 return file_name 37 ssh = SSHConnection() 38 #上傳文件、執行命令 39 ssh.connect() 40 r1 = ssh.cmd('df') 41 print(r1) 42 ssh.upload('s2.py','/home/s7.py') 43 ssh.close()
上面的例子是將命令寫入代碼中,並返回執行結果,下面我們就來介紹通過終端輸入命令,等待返回結果:
1.輸入命令點回車,執行命令,等待結果(linux終端默認只有點擊回車,io中的stdin才會有變化),不支持tab補全
2.每輸入一個字就給服務器傳過去,然后再點回車,服務器執行傳來的命令。(改變終端的模式)
第一個實例
1 import paramiko 2 import sys 3 import os 4 import socket 5 import select 6 import getpass 7 # from paramiko.py3compat import u py27需要注釋 8 tran = paramiko.Transport(('192.168.247.128',22,)) 9 tran.start_client() 10 tran.auth_password('root','111111') 11 #打開一個通道 12 chan = tran.open_session() 13 #獲取一個通道 14 chan.get_pty() 15 #激活器 16 chan.invoke_shell() 17 while True: 18 #監視用戶輸入和服務器返回數據 19 #sys.stdin 處理用戶輸入 20 #chan是之前創建的通道,用於就收服務器返回信息 21 readable,writeable,error = select.select([chan,sys.stdin,],[],[],1) 22 if chan in readable: #此處的chan是服務器通過執行命令,返回的結果 23 try: 24 #x = u(chan.recv(1024)) 25 x = chan.recv(1024) #py27寫法 26 if len(x) == 0: 27 print('\r\n*** EOF\r\n') 28 break 29 sys.stdout.write(x) 30 sys.stdout.flush() #刷新緩沖區,將內容打印到屏幕 31 except socket.timeout: 32 pass 33 if sys.stdin in readable: 34 inp = sys.stdin.readline() 35 chan.sendall(inp) 36 chan.close() 37 tran.close()
第二個實例
1 import paramiko 2 import sys 3 import os 4 import socket 5 import select 6 import getpass 7 import tty 8 import termios 9 # from paramiko.py3compat import u py27需要注釋 10 tran = paramiko.Transport(('192.168.247.128',22,)) 11 tran.start_client() 12 tran.auth_password('lwq','123') 13 #打開一個通道 14 chan = tran.open_session() 15 #獲取一個通道 16 chan.get_pty() 17 #激活器 18 chan.invoke_shell() 19 #獲取原tty屬性,目的是為了在操作完以后恢復終端原型 20 oldtty = termios.tcgetattr(sys.stdin) 21 try: 22 #為tty設置新屬性 23 #默認當前tty設備屬性 24 #輸入一行回車,執行 25 #ctrl +c 進程退出,遇到特殊字符,特殊處理 26 #這是為原始模式,不認識特殊字符號 27 #放置特殊字符應用在當前終端,如此設置,將所有的用戶輸入均發送到 遠程服務器 28 tty.setraw(sys.stdin.fileno()) 29 chan.settimeout(0.0) 30 while True: 31 #監視用戶輸入和服務器返回數據 32 #阻塞,直到句柄可讀 33 readable,writeable,error = select.select([chan,sys.stdin,],[],[],1) 34 if chan in readable: 35 try: 36 #x = u(chan.recv(1024)) 37 x = chan.recv(1024) #py27寫法 38 if len(x) == 0: 39 print('\r\n*** EOF\r\n') 40 break 41 sys.stdout.write(x) 42 sys.stdout.flush() 43 except socket.timeout: 44 pass 45 if sys.stdin in readable: 46 inp = sys.stdin.read(1) 47 if len(inp) == 0: 48 break 49 chan.send(inp) 50 finally: 51 #重新設置終端屬性 52 termios.tcsetattr(sys.stdin,termios.TCSADRAIN,oldtty) 53 chan.close() 54 tran.close()