使用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

posted @ 2021-04-12 16:29  迪克推多0  阅读(1188)  评论(0编辑  收藏  举报