和pexpect模塊功能類似,不過更簡潔。基於SSH遠程登陸,默認端口22shell
pip3 install paramiko 第三方模塊,提供了SSH遠程登陸服務器執行命令和下載文件的功能。服務器
基於用戶名和密碼的SSHClient登陸session
AutoAddPolicy:遇到陌生主機,自動把信任主機添加到host_allow列表ssh
RejectPolicy:遇到陌生主機直接拒絕socket
WarningPolicy:遇到陌生主機會提示,仍是會添加spa
connect(hostname, port, username, password, pkey, key_filename, timeout, allow_agent, look_for_keys, compress, sock, gss_auth,gss_kex, gss_deleg_creds, gss_host, banner_timeout, auth_timeout, gss_trust_dns, passphrase)code
exec_command(command, bufsize, timeout, get_pty, environment)對象
bufszie 緩衝區大小,默認爲-1blog
ssh = paramiko.SSHClient()#實例一個鏈接對象 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)#設置容許鏈接陌生主機 ssh.connect(hostname,username,port,password,pkey)#鏈接被管理機 stdio,stdout,stderr = ssh.exec_command(cmd)#發送命令 print(stdout.read().decode())#獲取命令結果 ssh.close()#關閉鏈接
基於密鑰的SSHClient登陸dns
鏈接端生成私鑰和公鑰,把公鑰給服務器,鏈接只需私鑰免密登陸
公鑰.pub後綴 私鑰沒後綴
sudo ssh-keygen -t rsa 建立密鑰文件
sudo ssh-copy-id -i 文件路徑.pub root@xxx.xxx.xxx.xxx 分發公鑰到服務器
paramiko.RSAKey.from_private_key_file('.ssh/id_rsa',password) 指定本地的RSA私鑰文件,默認目錄爲''.ssh/id_rsa"
若是建立密鑰文件時設置有密碼,就給參數password
沒設置就免密登陸
import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy) pkey = paramiko.RSAKey.from_private_key_file('.ssh/id_rsa') ssh.connect(hostname,port,username,pkey) stdio,stdout,stderr = ssh.exec_command(cmd) print(stdout.read(),stderr.read())
基於Transport用戶名和密碼登陸
Transport方式不止執行命令還能夠執行下載上傳命令
Transport(sock, default_window_size, default_max_packet_size, gss_kex, gss_deleg_creds)
import paramiko #基於Transport用戶名密碼方式登陸 tran = paramiko.Transport(('192.168.0.1',22)) tran.connect(username='root',password='123456') #實例一個SSHClient對象 ssh = paramiko.SSHClient() #將SSHClient的對象的transport指定爲以上的tran就能夠和SSHClient同樣執行命令 ssh._transport = tran #執行命令 stdio,stdout,stderr = ssh.exec_command(cmd) print(stdout.read())
基於Transport的密鑰登陸
pkey = paramiko.RSAKey.from_prviate_key_file('/.ssh/id_rsa') tran = paramiko.Transport(('192.168.0.1',22)) tran.connect(username,pkey) ssh = paramiko.SSHClient() ssh._transport = tran ssh.exec_command(cmd)
Transport對象下載上傳文件,SFTPClient方式
一個Transport實例至關於建立一個通道進行文件傳輸
SFTPClient.from_transport(t, window_size, max_packet_size) t爲建立的實例
from paramiko import SFTPClient,Transport def connect_(ip,username,pkey): try: tran = Transport((ip,22)) tran.connect(username,pkey) #把Transport實例通道傳進來,指定鏈接的通道 sftp = SFTPClient.from_transport(tran) except Exception: return None return sftp def upload_file(sftp,localpath,remotepath): #上傳文件 sftp.put(localpath,remotepath) def download_file(sftp,localpath,remotepath): #下載文件 sftp.get(localpath,remotepath) def main(): pkey = RSAKey.from_prviate_key_file('/.ssh/id_rsa') sftp = connect_(ip, username, pkey) if sftp: upload_file(sftp, localpath, remotepath) #download_file(sftp, localpath, remotepath) sftp.close() if __name__ == '__main__': main()
接受命令的虛擬終端
1.開一個socket鏈接 tran = Transport((ip,port))
2.開啓一個客戶端 tran.start_client()
3.登陸服務器 tran.auth_password(username, password, event, fallback)
4.建立一個會話終端對象 channel = tran.open_session(window_size=None, max_packet_size=None, timeout=None )
5.獲取終端 channel.get_pty()
6.激活終端 channel.invoke_shell()
7.發送命令 channel.sendall(cmd)
8.獲取命令結果 channel.recv(1024)
#相似xshell的終端模擬軟件,保持一個shell狀態 import paramiko import os import sys import select def connect_(username,ip,password): try: tran = paramiko.Transport((ip,22))#創建一個socket通道 tran.start_client() #啓動一個客戶端 tran.auth_password(username=username, password=password)#用戶名和密碼登陸 channel = tran.open_session()#打開一個會話通道 channel.get_pty()#獲取終端 channel.invoke_shell()#激活終端 except paramiko.ssh_exception.SSHException: print('鏈接錯誤') return None return channel
# 下面就能夠執行你全部的操做,用select實現 # 對輸入終端sys.stdin和 通道進行監控, # 當用戶在終端輸入命令後,將命令交給channel通道,這個時候sys.stdin就發生變化,select就能夠感知 # channel的發送命令、獲取結果過程其實就是一個socket的發送和接受信息的過程 def main(): username = 'root' ip = '192.168.0.1' password = '123456' channel = connect_(username, ip, password) if channel: while True: readlist,writelist,errlist = select.select([channel,sys.stdin],[],[]) #發送命令 if sys.stdin in readlist: cmd = sys.stdin.read(1) channel.sendall(cmd) #獲取命令結果 if channel in readlist: res = channel.recv(1024)#接受結果 if not res:#判斷結果是否爲空 print('斷開鏈接') break sys.stdout.write(res.decode())#輸出到屏幕 sys.stdout.flush()#刷新緩衝區 channel.close() tran.close() if __name__ == '__main__': main()