1、paramiko模塊介紹
paramiko模塊提供了基於ssh連接,進行遠程登錄服務器執行命令和上傳下載文件的功能。這是一個第三方的軟件包,使用之前需要安裝。
2、paramiko的使用方法
(1)基於用戶名和密碼的sshclient方式登陸
#!/usr/bin/env python #coding:utf8 import paramiko #創建sshclient對象 ssh = paramiko.SSHClient() #允許將信任的主機自動加入到host_allow 列表,此方法必須放在connect方法的前面 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #調用connect方法連接服務器 ssh.connect(hostname='172.16.32.129',port=2323,username='root',password='123.com') while True: input_command = input('>>>:') if input_command == 'quit': break #執行命令,輸出結果在stdout中,如果是錯誤則放在stderr中 stdin,stdout,stderr = ssh.exec_command(input_command) result = stdout.read() #read方法讀取輸出結果 if len(result) == 0: #判斷如果輸出結果長度等於0表示為錯誤輸出 print(stderr.read()) else: print(str(result,'utf-8')) ssh.close()
封裝方法,隱藏屬性:
#config.ini文件 [ssh] host=172.16.32.129 port=2323 user=root pwd=123.com timeout=1.1 #封裝ssh類 #!/usr/bin/env python #coding:utf8 import configparser,paramiko class parmikoclient(object): def __init__(self,ini_file): self.config=configparser.ConfigParser() self.config.read(ini_file) self.host = self.config.get('ssh','host') self.port = self.config.get('ssh', 'port') self.user = self.config.get('ssh', 'user') self.pwd = self.config.get('ssh', 'pwd') self.timeout = self.config.get('ssh', 'timeout') self.client=paramiko.SSHClient() self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.client.connect(hostname=self.host,port=self.port,username=self.user,password=self.pwd,timeout=float(self.timeout)) def run_ssh(self,cmd_command): # 執行命令,輸出結果在stdout中,如果是錯誤則放在stderr中 stdin,stdout,stderr = self.client.exec_command(cmd_command) result = stdout.read() # read方法讀取輸出結果 if len(result) == 0: # 判斷如果輸出結果長度等於0表示為錯誤輸出 print(stderr.read().decode()) else: print(str(result, 'utf-8')) def close(self): self.client.close() if __name__ == '__main__': client_cmd = parmikoclient('config.ini') while True: cmd_input=input('>>>:') client_cmd.run_ssh(cmd_input) if cmd_input == 'quit': client_cmd.close()
通過transport方式登錄:
#!/usr/bin/env python #coding:utf8 import paramiko #實例化一個transport對象 transport = paramiko.Transport(('172.16.32.129',2323)) #建立連接 transport.connect(username='root',password='123') #建立ssh對象 ssh = paramiko.SSHClient() #綁定transport到ssh對象 ssh._transport=transport #執行命令 stdin,stdout,stderr=ssh.exec_command('df') #打印輸出 print(stdout.read().decode()) #關閉連接 transport.close()
(2)基於密鑰的sshclient方式登陸
#!/usr/bin/env python #coding:utf8 #必須先將公鑰文件傳輸到服務器的~/.ssh/authorized_keys中 import paramiko # 指定本地的RSA私鑰文件,如果建立密鑰對時設置的有密碼,password為設定的密碼,如無不用指定password參數 pkey = paramiko.RSAKey.from_private_key_file('id_rsa_1024') #建立連接 ssh = paramiko.SSHClient() #允許將信任的主機自動加入到known_hosts列表 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname='172.16.32.129',port=2323,username='root',pkey=pkey) #指定密鑰連接 #執行命令 stdin,stdout,stderr=ssh.exec_command('free -m') print(stdout.read().decode()) ssh.close()
以上需要確保被訪問的服務器對應用戶.ssh目錄下有authorized_keys文件,也就是將服務器上生成的公鑰文件保存為authorized_keys。並將私鑰文件作為paramiko的登陸密鑰
transport封裝密鑰登陸:
#!/usr/bin/env python #coding:utf8 #必須先將公鑰文件傳輸到服務器的~/.ssh/authorized_keys中 import paramiko # 指定本地的RSA私鑰文件,如果建立密鑰對時設置的有密碼,password為設定的密碼,如無不用指定password參數 pkey = paramiko.RSAKey.from_private_key_file('id_rsa_1024') #創建transport對象綁定主機和端口,指定用戶和密鑰連接 transport = paramiko.Transport(('172.16.32.129',2323)) transport.connect(username='root',pkey=pkey) ssh = paramiko.SSHClient() ssh._transport = transport #類屬性賦值 #允許將信任的主機自動加入到known_hosts列表 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #執行命令 stdin,stdout,stderr=ssh.exec_command('free -m') print(stdout.read().decode()) ssh.close()
(3)SFTP文件傳輸
#!/usr/bin/env python #coding:utf8 import paramiko #實例化transport對象,並建立連接 transport = paramiko.Transport(('172.16.32.129',2323)) transport.connect(username='root',password='123.com') #實例化sftp對象,指定連接對象 sftp = paramiko.SFTPClient.from_transport(transport) #上傳文件 sftp.put(localpath='id_rsa_1024',remotepath='/root/idrsa1024.txt') #下載文件 sftp.get(remotepath='/root/idrsa1024.txt',localpath='idrsa1024_back.txt') #關閉連接 transport.close()
實現一個類似xshell工具的功能,登錄以后可以輸入命令回車后就返回結果:
import paramiko import os import select import sys # 建立一個socket trans = paramiko.Transport(('192.168.2.129', 22)) # 啟動一個客戶端 trans.start_client() # 如果使用rsa密鑰登錄的話 ''' default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') prikey = paramiko.RSAKey.from_private_key_file(default_key_file) trans.auth_publickey(username='super', key=prikey) ''' # 如果使用用戶名和密碼登錄 trans.auth_password(username='super', password='super') # 打開一個通道 channel = trans.open_session() # 獲取終端 channel.get_pty() # 激活終端,這樣就可以登錄到終端了,就和我們用類似於xshell登錄系統一樣 channel.invoke_shell() # 下面就可以執行你所有的操作,用select實現 # 對輸入終端sys.stdin和 通道進行監控, # 當用戶在終端輸入命令后,將命令交給channel通道,這個時候sys.stdin就發生變化,select就可以感知 # channel的發送命令、獲取結果過程其實就是一個socket的發送和接受信息的過程 while True: readlist, writelist, errlist = select.select([channel, sys.stdin,], [], []) # 如果是用戶輸入命令了,sys.stdin發生變化 if sys.stdin in readlist: # 獲取輸入的內容 input_cmd = sys.stdin.read(1) # 將命令發送給服務器 channel.sendall(input_cmd) # 服務器返回了結果,channel通道接受到結果,發生變化 select感知到 if channel in readlist: # 獲取結果 result = channel.recv(1024) # 斷開連接后退出 if len(result) == 0: print("\r\n**** EOF **** \r\n") break # 輸出到屏幕 sys.stdout.write(result.decode()) sys.stdout.flush() # 關閉通道 channel.close() # 關閉鏈接 trans.close()
支持tab自動補全
import paramiko import os import select import sys import tty import termios ''' 實現一個xshell登錄系統的效果,登錄到系統就不斷輸入命令同時返回結果 支持自動補全,直接調用服務器終端 ''' # 建立一個socket trans = paramiko.Transport(('192.168.2.129', 22)) # 啟動一個客戶端 trans.start_client() # 如果使用rsa密鑰登錄的話 ''' default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') prikey = paramiko.RSAKey.from_private_key_file(default_key_file) trans.auth_publickey(username='super', key=prikey) ''' # 如果使用用戶名和密碼登錄 trans.auth_password(username='super', password='super') # 打開一個通道 channel = trans.open_session() # 獲取終端 channel.get_pty() # 激活終端,這樣就可以登錄到終端了,就和我們用類似於xshell登錄系統一樣 channel.invoke_shell() # 獲取原操作終端屬性 oldtty = termios.tcgetattr(sys.stdin) try: # 將現在的操作終端屬性設置為服務器上的原生終端屬性,可以支持tab了 tty.setraw(sys.stdin) channel.settimeout(0) while True: readlist, writelist, errlist = select.select([channel, sys.stdin,], [], []) # 如果是用戶輸入命令了,sys.stdin發生變化 if sys.stdin in readlist: # 獲取輸入的內容,輸入一個字符發送1個字符 input_cmd = sys.stdin.read(1) # 將命令發送給服務器 channel.sendall(input_cmd) # 服務器返回了結果,channel通道接受到結果,發生變化 select感知到 if channel in readlist: # 獲取結果 result = channel.recv(1024) # 斷開連接后退出 if len(result) == 0: print("\r\n**** EOF **** \r\n") break # 輸出到屏幕 sys.stdout.write(result.decode()) sys.stdout.flush() finally: # 執行完后將現在的終端屬性恢復為原操作終端屬性 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) # 關閉通道 channel.close() # 關閉鏈接 trans.close()