使用python的paramiko模塊實現ssh遠程登錄及sftp上傳下載


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM