最近有个项目需要一个跨服务器之间的文件上传和下载
下面会用到Python的paramiko模块来实现功能

paramiko是用python写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。利用该模块,可以方便的进行ssh连接和sftp协议进行sftp文件传输以及远程命令执行。

主要实现代码如下:(代码中加入了日志打印,方便定位问题)

文件的下拉模块
import os
from configparser import RawConfigParser
import paramiko
import logging

'''
对于远程服务器的指定路径,进行拉取文件名列表,可以根据筛选规则进行选择下拉文件
'''

# 生成日志文件
logging.basicConfig(filename='get_file.log', level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


def read_config():
    # 当配置文件的value中有符号时,configparser.ConfigParser()读取就会报错,就要采用configparser.RawConfigParser()进行读取
    cfg = RawConfigParser()
    cfg.read('./config.ini',encoding='utf-8')
    host_ip = cfg.get('get','host_ip')
    host_port = cfg.get('get','host_port')
    host_username = cfg.get('get','host_username')
    host_password = cfg.get('get','host_password')
    remote_path = cfg.get('get','remote_path')
    local_path = cfg.get('get','local_path')
    get_file_key = cfg.get('get','get_file_key')
    get_file_suffix = cfg.get('get','get_file_suffix')

    scp_config = {}

    scp_config['host_ip'] = host_ip
    scp_config['host_port'] = host_port
    scp_config['host_username'] = host_username
    scp_config['host_password'] = host_password
    scp_config['remote_path'] = remote_path
    scp_config['local_path'] = local_path
    scp_config['get_file_key'] = get_file_key
    scp_config['get_file_suffix'] = get_file_suffix

    return scp_config

def RemoteScp(host_ip, host_port, host_username, host_password, remote_path, local_path,get_file_key,get_file_suffix):
    scp = paramiko.Transport((host_ip, host_port))
    scp.connect(username=host_username, password=host_password)
    sftp = paramiko.SFTPClient.from_transport(scp)
    key = get_file_key
    suffix_name = get_file_suffix
    suffix_len = len(suffix_name)
    try:
        remote_files = sftp.listdir(remote_path)
        for file in remote_files:   #遍历读取远程目录里的所有文件
            if file.find(key) != -1:
                # 判断需要上传的文件的后缀(例如 .json)
                if file[-int(suffix_len):] == suffix_name:
                    local_file = local_path + file
                    remote_file = remote_path + file
                    try:
                        sftp.get(remote_file, local_file)
                        logger.info(file + '该文件已经下拉成功')
                    except Exception as e:
                        logger.info("报错:大概率是有含有关键词的文件夹,sftp的put&get方法均无法操作文件夹")
                        logger.info(str(e))
    except IOError:   #  如果目录不存在则抛出异常
        return ("remote_path or local_path is not exist")
        logger.info('remote_path or local_path is not exist')
    scp.close()

if __name__ == '__main__':
    scp_config = read_config()
    # 远程服务器IP
    host_ip = str(scp_config['host_ip'])
    # 远程服务器端口,配置文件读出来的是str类型的端口号,但是要传入的端口号必须是int类型的
    host_port = int(scp_config['host_port'])
    # 远程服务器用户名
    host_username = str(scp_config['host_username'])
    # 远程服务器密码
    host_password = str(scp_config['host_password'])
    # 这个是远程目录
    remote_path = str(scp_config['remote_path'])
    # 这个是本地目录
    local_path = str(scp_config['local_path'])
    # 拉取文件名包含关键词
    get_file_key = str(scp_config['get_file_key'])
    # 拉去文件的文件名后缀,用于进一步区分要上传的文件
    get_file_suffix = str(scp_config['get_file_suffix'])
    # 调用方法
    RemoteScp(host_ip, host_port, host_username, host_password, remote_path, local_path,get_file_key,get_file_suffix)
文件的上传
import os
from configparser import RawConfigParser
import paramiko
import logging

'''
对于远程服务器的指定路径,进行拉取文件名列表,可以根据筛选规则进行选择下拉文件
'''

# 生成日志文件
logging.basicConfig(filename='put_file.log', level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


def read_config():
    # 当配置文件的value中有符号时,configparser.ConfigParser()读取就会报错,就要采用configparser.RawConfigParser()进行读取
    cfg = RawConfigParser()
    cfg.read('./config.ini',encoding='utf-8')
    host_ip = cfg.get('put','host_ip')
    host_port = cfg.get('put','host_port')
    host_username = cfg.get('put','host_username')
    host_password = cfg.get('put','host_password')
    remote_path = cfg.get('put','remote_path')
    local_path = cfg.get('put','local_path')
    put_file_key = cfg.get('put', 'put_file_key')
    put_file_suffix = cfg.get('put', 'put_file_suffix')

    scp_config = {}

    scp_config['host_ip'] = host_ip
    scp_config['host_port'] = host_port
    scp_config['host_username'] = host_username
    scp_config['host_password'] = host_password
    scp_config['remote_path'] = remote_path
    scp_config['local_path'] = local_path
    scp_config['put_file_key'] = put_file_key
    scp_config['put_file_suffix'] = put_file_suffix

    return scp_config

def RemoteScp(host_ip, host_port, host_username, host_password, remote_path, local_path,put_file_key,put_file_suffix):
    scp = paramiko.Transport((host_ip, host_port))
    scp.connect(username=host_username, password=host_password)
    sftp = paramiko.SFTPClient.from_transport(scp)
    files = os.listdir(local_path)
    key = put_file_key
    suffix_name = put_file_suffix
    suffix_len = len(suffix_name)
    try:
        for file in files:
            if file.find(key) != -1:
                # 判断需要上传的文件的后缀(例如 .json)
                if file[-int(suffix_len):] == suffix_name:
                    local_file = local_path + file
                    remote_file = remote_path + file
                    try:
                        sftp.put(local_file, remote_file)
                        logger.info(file + '该文件已经推送成功')
                        # 删除已上完成的文件
                        os.remove(local_file)
                        logger.info(file + '该文件已经删除成功')
                    except Exception as e:
                        logger.info("报错:大概率是有含有关键词的文件夹,sftp的put&get方法均无法操作文件夹")
                        logger.info(str(e))
    except Exception as e:
        logger.info("遍历文件名列表不成功,具体原因需要根据错误日志分析")
        logger.info(str(e))
    scp.close()

if __name__ == '__main__':
    scp_config = read_config()
    # 远程服务器IP
    host_ip = str(scp_config['host_ip'])
    # 远程服务器端口,配置文件读出来的是str类型的端口号,但是要传入的端口号必须是int类型的
    host_port = int(scp_config['host_port'])
    # 远程服务器用户名
    host_username = str(scp_config['host_username'])
    # 远程服务器密码
    host_password = str(scp_config['host_password'])
    # 这个是远程目录
    remote_path = str(scp_config['remote_path'])
    # 这个是本地目录
    local_path = str(scp_config['local_path'])
    # 推送文件名包含关键词
    put_file_key = str(scp_config['put_file_key'])
    # 推送文件的文件名后缀,用于进一步区分要上传的文件
    put_file_suffix = str(scp_config['put_file_suffix'])
    # 调用方法
    RemoteScp(host_ip, host_port, host_username, host_password, remote_path, local_path,put_file_key,put_file_suffix)
配置文件如下
[get]
# 远程服务器IP
host_ip = 10.10.10.10
# 远程服务器端口
host_port = 22
#远程服务器用户名
host_username = root
#远程服务器密码
host_password = 111111
#这个是需要拉取文件所在的远程目录,目录地址最后要加/
remote_path = /opt/
#这个是把拉取文件存放的本地目录,目录地址最后要加/
local_path = C:/Users/
# 拉取文件名包含关键词
get_file_key = int
# 下拉的文件格式,即文件后缀名,注意:需要写     .   ,不然会和后缀名相同的文件夹混了
get_file_suffix = .zip

[put]
# 远程服务器IP
host_ip = 10.10.10.10
# 远程服务器端口
host_port = 22
#远程服务器用户名
host_username = root
#远程服务器密码
host_password = 111111
#这个是推送文件所在的本地目录,目录地址最后要加/
local_path = C:/Users/
#这个是接受推送文件的远程目录,目录地址最后要加/
remote_path = /opt/
# 上传文件名包含关键词
put_file_key = int
# 上传的文件格式,即文件后缀名,注意:需要写     .   ,不然会和后缀名相同的文件夹混了
put_file_suffix = .json