概述
目录
前言
安装
编写
工具类SFTP
JSON配置文件
实现
打包
使用
总结
前言
多台服务器同步配置文件是一个常用的需求。尤其是负载均衡下,修改一点东西可能需要同步到N台服务器上。人工同步略微有点蛋疼。
Linux有个scp复制,需要搭配expect来使用。但是说实话,我是不愿意写bash脚本的。前段日子写zabbix的监控脚本就感觉自己头皮发麻。
python有一个paramiko库同样可以实现文件分发。接下来我们就来看看如何实现。
为了方便,这里采用了json配置文件的形式。同时最终我会用pyinstaller打包成可执行文件。
python版本:3.6.8
paramiko版本:2.7.1
pyinstaller版本:3.6
开发环境:Linux Centos7
最终运行环境:Linux Centos7
安装
不用多说。
pip install paramiko
编写
工具类SFTP
里面实现了初始化、连接、断开连接、上传文件、创建目录功能。这里主要是使用了递归思路实现了文件夹的创建。
import os
import paramiko
class SFTP(object):
"""
SFTP 工具类
"""
def __init__(self, host, port, username, password):
self.host = host
self.port = port
self.username = username
self.password = password
self.manager = None
self.client = None
def connect(self):
"""
连接sftp服务器
"""
manager = paramiko.Transport((self.host, self.port))
manager.connect(username=self.username, password=self.password)
self.manager = manager
client = paramiko.SFTPClient.from_transport(manager)
self.client = client
def quit(self):
"""
断开sftp服务器连接
"""
if not self.client:
self.client.close()
if not self.manager:
self.manager.close()
def exists(self, remote_path):
"""
判断服务器上路径是否存在
:param remote_path: 服务器路径
:return:
"""
try:
self.client.stat(remote_path)
return True
except FileNotFoundError:
return False
def upload(self, local_file, item, remote_path=''):
"""
上传文件到服务器
:param local_file: 本地文件路径
:param item: 文件相对路径
:param remote_path: 服务器文件夹路径
:return:
"""
if not os.path.isfile(local_file):
raise FileNotFoundError('File %s is not found' % local_file)
# 得到服务器文件所在文件夹的路径
remote_dir = os.path.join(remote_path, os.path.split(item)[0])
# 创建文件夹
self.mkdir(remote_dir)
# 得到服务器文件的路径
remote_file = os.path.join(remote_path, item)
# 上传文件
print("*** Upload ", local_file, " to ", remote_file, " success ***")
self.client.put(local_file, remote_file)
def mkdir(self, path):
"""
根据路径递归创建文件夹
:param path: 文件夹路径
:return:
"""
if self.exists(path):
return
self.mkdir(os.path.dirname(path))
self.client.mkdir(path)
JSON配置文件
按照格式,注释代码里再说
{
"servers": [{
"ip": "47.105.154.123",
"username": "root",
"password": "123",
"port": 22,
"remote_path": "/home/test",
"local_path": "/home/test",
"excludes": [
"img"
]
},
{
"ip": "47.105.189.1234",
"username": "root",
"password": "123",
"port": 22,
"remote_path": "/home/test",
"local_path": "/home/test",
"excludes": [
"img"
]
}
]
}
实现
接下来就是调用代码。读取
if __name__ == '__main__':
print("******* program start *******")
servers = None
# 获取脚本所在位置
script_path = os.path.dirname(os.path.realpath(sys.argv[0]))
with io.open(script_path + "/servers.json", "r", encoding="utf-8") as json_file:
servers = json.load(json_file)
json_file.close()
for server in servers["servers"]:
host = server["host"] # host
username = server["username"] # 用户名
password = server["password"] # 密码
port = server["port"] # 端口
remote_path = server["remote_path"] # 服务器目标路径
local_path = server["local_path"] # 本地文件路径
excludes = server["excludes"] # 排除文件或文件夹夹路径
sftp = SFTP(host , port, username, password)
sftp.connect()
print("******* ", host, " start upload*******")
if not sftp.exists(remote_path):
sftp.mkdir(remote_path)
item_list = os.listdir(local_path)
# 遍历目录下所有文件
while len(item_list) > 0:
item = item_list.pop()
# 如果文件或文件夹在排除名单内,跳过本次循环
if item in excludes:
continue
filename = os.path.join(local_path, item)
# 如果为目录,将目录下的文件加入遍历队列中
if os.path.isdir(filename):
path_list = []
for i in os.listdir(filename):
path_list.append(os.path.join(item, i))
item_list.extend(path_list)
continue
sftp.upload(filename, item, remote_path)
print("******* ", ip, " end upload *******")
print("******* program finish *******")
这里对上面代码进行解释:
1.获取当前文件路径
因为最终会打包成可执行文件,json文件理应和可执行文件在同级目录下。
一开始我使用相对路径,用python 执行时候没有问题,用pyinstaller打包后会出现路径异常,即配置文件变成绝对路径。
with io.open("servers.json", "r", encoding="utf-8") as json_file:
因此改成先获取可执行文件的路径
script_path = os.path.dirname(os.path.realpath(sys.argv[0]))
with io.open(script_path + "/servers.json", "r", encoding="utf-8") as json_file:
2.读取json
with io.open(script_path + "/servers.json", "r", encoding="utf-8") as json_file:
servers = json.load(json_file)
json_file.close()
3.遍历读取到的服务器信息。
for server in servers["servers"]:
4.连接SFTP服务
sftp = SFTP(host, port, username, password)
sftp.connect()
5.目录不存在则创建目录
if not sftp.exists(remote_path):
sftp.mkdir(remote_path)
6.开始遍历目录下的所有文件。利用栈的思想,目录其实就是一颗文件树。
item_list = os.listdir(local_path)
# 遍历目录下所有文件
while len(item_list) > 0:
item = item_list.pop()
# 如果文件或文件夹在排除名单内,跳过本次循环
if item in excludes:
continue
filename = os.path.join(local_path, item)
# 如果为目录,将目录下的文件加入遍历队列中
if os.path.isdir(filename):
path_list = []
for i in os.listdir(filename):
path_list.append(os.path.join(item, i))
item_list.extend(path_list)
continue
7.上传文件
sftp.upload(filename, item, remote_path)
打包
打包就不说了,用pyinstaller工具,最容易的方式就是把工具类和实现方法放在一个文件里。
pyinstaller -F send.py
关于pip下载这里还是要说两句,linux下要用pip3按照,不要用pip。否则下载的包或工具只能python2使用。
如果不小心用pip安装了,也别怕。用pip uninstall 卸载掉就好了。
使用
最后打包出来的可执行文件和json配置文件放在一个目录里,执行文件即可。以后只需要修改json配置就可以改动。
命名有点不同,不用介意
总结
打包成可执行文件主要是要给别人用,他又不想配置python环境~
用python的速度没有用linux自带scp快,但是python写的更得心应手一点。
有什么问题可以评论或者私信我,每日在线解(LIAO)疑(SAO)。
我是大誌,一位准备996的卑微码农????,觉得好用记得点赞收藏!!!
最后
以上就是淡淡板凳为你收集整理的一看就懂!python实现多服务器文件分发前言安装编写打包使用总结的全部内容,希望文章能够帮你解决一看就懂!python实现多服务器文件分发前言安装编写打包使用总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复