paramiko是一個用於做遠程控制的模塊,使用該模塊可以對遠程服務器進行命令或文件操作,paramiko是用python語言寫的一個模塊,遵循SSH2協議,支持以加密和認證的方式,進行遠程服務器的連接。
一、安裝paramiko
1.命令行使用pip3安裝
由於 paramiko 模塊內部依賴pycrypto,所以先下載安裝pycrypto,再安裝paramiko
pip3 install pycrypto
pip3 install paramiko
2.直接pycharm內安裝
進入pycharm,執行‘import paramiko',發現沒有paramiko,將鼠標放在paramiko上,按‘alt + enter‘,在出現的界面上選擇第一個'Install package paramiko'進行安裝。等待出現'Package installed successfully'表明安裝成功。
二、使用
1.SSHClient
用於連接遠程服務器並執行基本命令
①基於用戶名密碼連接:
import paramiko ##1.創建一個ssh對象 client = paramiko.SSHClient() #2.允許連接不在know_hosts文件中的主機,即之前沒有連接過的主機 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #3.連接服務器 client.connect(hostname='172.25.254.31', port=22, username='root', password='123456') #4.執行操作 stdin,stdout, stderr = client.exec_command('hostname') #5.獲取命令執行的結果 result=stdout.read().decode('utf-8') print(result) #6.關閉連接 client.close()
登錄失敗提示報錯案例:
from paramiko.ssh_exception import NoValidConnectionsError from paramiko.ssh_exception import AuthenticationException import paramiko def ssh_connect(): #1.創建一個ssh對象,並允許連接之前沒有連接的主機 client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #2.連接服務器 try: client.connect(hostname=hostname, port=port, username=username, password=passwd) print('正在連接主機%s......'%(hostname)) except NoValidConnectionsError as e: ###用戶不存在時的報錯 print("連接失敗") except AuthenticationException as t: ##密碼錯誤的報錯 print('密碼錯誤') else: #3.執行操作 stdin,stdout, stderr = client.exec_command(cmd) #4.獲取命令執行的結果 result=stdout.read().decode('utf-8') print(result) #5.關閉連接 finally: client.close()
②基於公鑰密鑰連接:
import paramiko # id_rsa為本地局域網密鑰文件 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') # 創建SSH對象 client = paramiko.SSHClient() # 允許連接不在know_hosts文件中的主機 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 連接服務器 client.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key) # 執行命令 stdin, stdout, stderr = client.exec_command('df') # 獲取命令結果 result = stdout.read().decode('utf-8')
# 關閉連接 ssh.close()
2.SFTPClient
用於連接遠程服務器並執行上傳下載
①基於用戶名密碼上傳下載:
import paramiko transport = paramiko.Transport(('hostname',22)) transport.connect(username='root',password='123456') 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()
②基於公鑰密鑰上傳下載:
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') transport = paramiko.Transport(('hostname', 22)) transport.connect(username='root', 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()
3.paramiko通過堡壘機在遠程訪問服務器
import paramiko import sys blip="10.254.24.100" #堡壘機地址 bluser="xxx" #堡壘機用戶名 blpasswd='xxx' #堡壘機密碼 hostname='10.100.255.220' #業務服務器地址 username='root' #業務服務器用戶名 password='xxxx' #業務服務器密碼 port=22 #堡壘機連接端口 def receive_data(match,receive_len=9999): buff='' resp='' while not buff.endswith(match): #接受到的數據末尾如果是match,結束循環 try: resp = channel.recv(receive_len) #遠端接受數據 except Exception as e: print('Eroor info:%s connection time' % str(e)) channel.close() ssh.close() sys.exit() buff += resp.decode('utf-8') #resp為bytes,需轉成str,才可進行字符串拼接成buff return buff def save_file(filename,mode,content): with open(filename,mode,encoding='utf-8') as f: f.write(content) if __name__ == '__main__': sum ='' paramiko.util.log_to_file('login.log') ssh=paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=blip,port=port,username=bluser,password=blpasswd) channel=ssh.invoke_shell() #創建會話,開啟命令調用 channel.settimeout(20) #20秒超時 match_list=['page: ','account: ','Input account: ',"'s password: ",'# ','# '] send_list=['0\n','%s\n'%blip,'1\n','%s\n'%username,'%s\n'%password,'ifconfig\n'] for index,per_match in enumerate(match_list): channel.send(send_list[index]) buff=receive_data(per_match) sum +=buff # print(buff) print(sum) #打印整個過程的交互數據 save_file('6_3_2_operate.log','w',sum) channel.close() ssh.close()
4.paramiko通過堡壘機登錄業務機上傳文件
#客戶端先上傳文件到堡壘機,在通過堡壘機上傳文件到業務服務器 import paramiko import os,sys,time blip='172.17.9.68' #堡壘機信息 bluser='root' blpasswd='xxx' hostname='172.17.9.70' #定義業務服務器信息 username='root' password='xxxx' tmpdir="/root" remotedir='/root' localpath='6_1_login.log' #本地源文件路徑 tmppath=tmpdir+'/6_1_login.log' #堡壘機臨時路徑 remotepath=remotedir+'/6_1_login.log' #業務主機目標路徑 port =22 passinfo="'s password: " paramiko.util.log_to_file('syslogin.log') t=paramiko.Transport((blip,port)) t.connect(username=bluser,password=blpasswd) sftp=paramiko.SFTPClient.from_transport(t) sftp.put(localpath=localpath,remotepath=tmppath) #上傳本地文件源到堡壘機臨時路徑 sftp.close() ssh=paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=blip,username=bluser,password=blpasswd) channel=ssh.invoke_shell() channel.settimeout(20) buff="" resp="" print ('scp '+tmpdir+' '+username+'@'+hostname+':'+remotepath+'\n') #scp中轉目錄文件到目標主機 channel.send('scp '+tmppath+' '+username+'@'+hostname+':'+remotepath+'\n') while not buff.endswith(passinfo): try: resp=channel.recv(9999) except Exception as e: print('Error info:%s connection time.'%(str(e))) channel.close() ssh.close() sys.exit() buff +=resp.decode('utf-8') # print(buff) if not buff.find('yes/no') == -1: #找到yes/no字符,執行以下語句 channel.send('yes\n') buff='' channel.send(password+'\n') buff='' while not buff.endswith('# '): #buff末尾不是'# '字符,就執行以下語句 resp=channel.recv(9999) if not resp.decode('utf-8').find(passinfo) ==-1: #找到‘s password:字符就執行以下語句,說明密碼錯誤 print ('Error info:Authentication failed.') channel.cholse() ssh.close() sys.exit() buff +=resp.decode('utf-8') print (buff) channel.close() ssh.close() 堡壘機模式下的文件上傳
參考原文:https://www.cnblogs.com/python-nameless/p/6855804.html
https://www.cnblogs.com/lisenlin/p/9201781.html