修改了几个部分:
- 支持配置多台服务器,不配置端口号时,默认端口为22
- 支持按目录递归复制
- print函数不直接拼接字符串,改成了格式化字符串
递归复制的代码参考了一些网上的代码,其中
try:
sftp.put(real_local_path, real_server_path)
except:
sftp.mkdir(os.path.join(server_path, dirpath).replace("\\", "/"))
sftp.put(real_local_path, real_server_path)
这段在很多示例中是先采用 mkdir 创建目录,捕捉到异常后pass,然后再复制文件。具体考虑到我的实际情况,是文件夹已经存在的情况比较多,所以采取首先尝试同步文件的策略。
由于是单线程,一条连接,所以在需要同步的文件多的情况下,效率还是个很大的问题。
修改后的源码:
#!-*- coding: utf-8 -*-
"""
练手小程序
"""
import json
import paramiko
import os
# 递归复制文件
def put_recursive(sftp, local_path, server_path):
sync_file_count = 0
local_path_split = os.path.split(local_path)
os.chdir(local_path_split[0])
local_path_parent = local_path_split[1]
for (dirpath, dirnames, files) in os.walk(local_path_parent):
for file in files:
real_local_path = os.path.join(dirpath, file)
real_server_path = os.path.join(server_path, dirpath, file).replace("\\", "/")
try:
sftp.put(real_local_path, real_server_path)
except:
sftp.mkdir(os.path.join(server_path, dirpath).replace("\\", "/"))
sftp.put(real_local_path, real_server_path)
print("已同步本地文件: '{}' 到服务器路径:'{}'".format(local_path_split[0] + real_local_path, real_server_path))
sync_file_count += 1
return sync_file_count
def main():
default_port = 22
global_sync_file_count = 0
with open("config.json") as config_file:
config = json.load(config_file)
print("读取配置文件成功!")
host_config = config["host_config"]
for host in host_config:
try:
ip = host["ip"]
port = host.get("port", default_port)
username = host["username"]
password = host["password"]
path_list = host["path_list"]
sync_file_count = 0
print("开始连接远程服务器:{}".format(ip))
transport = paramiko.Transport((ip, port))
transport.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(transport)
print("连接远程服务器 '{}' 成功!".format(ip))
print("********同步文件到服务器 '{}' --开始".format(ip))
for path in path_list:
sync_file_count = put_recursive(sftp, path["local_path"], path["server_path"])
global_sync_file_count += sync_file_count
print("********同步文件到服务器 '{}' --结束,同步了 {} 个文件".format(ip, sync_file_count))
except IOError:
pass
finally:
sftp.close()
transport.close()
print("成功关闭与远程服务器'{}'的连接".format(ip))
print("已经全部同步完成!一共同步了 {} 个文件!".format(global_sync_file_count))
if __name__ == '__main__':
import time
main()
print("共用了", time.clock(), "秒")
配置文件:
{
"host_config":[
{
"ip":"127.0.0.1",
"port":666,
"username":"root",
"password":"root",
"path_list":[
{
"local_path":"G:/Java",
"server_path":"/home"
}
]
},
{
"ip":"127.0.0.1",
"username":"root",
"password":"root",
"path_list":[
{
"local_path":"G:/uploadFile",
"server_path":"/home"
}
]
}
]
}