最近有个项目需要一个跨服务器之间的文件上传和下载
下面会用到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