需求

项目需要定时移植多个客户服务器的文件到公司服务器上,确保文件定时同步和生成监控日志

机制原理

1.客户和公司服务器同时安装vpn,绕过复杂的网关,linux下使用的OpenVPN

2.服务器定时运行Python移植脚本

3.使用Python的原因,支持多线程和完善ftp类库

代码实现(Python)

Python脚本

# coding=utf-8
import os
import ftplib
import threading
import time
import pymysql # ftp操作类
class myFtp:
# 初始化类,连接生产服务器,链接mysql
def __init__(self, host, port, user, passwd, dbCursor): self.ftp = ftplib.FTP()
self.msgHost = host
self.dbCursor = dbCursor
self.user = user
self.passwd = passwd
self.filepath = '/'
try:
self.ftp.connect(host, port)
msgInsert(self.user, "info", "ftp连接成功", self.dbCursor)
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " " + self.msgHost + " ftp连接成功")
except:
msgInsert(self.user, "error", "ftp连接失败", self.dbCursor)
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " " + self.msgHost + " ftp连接失败") # ftp错误级别
self.ftp.set_debuglevel(0)
# self.ftp.set_pasv(0)
try:
self.ftp.login(user, passwd)
self.loginSuccess = 1
msgInsert(self.user, "info", "ftp用户登录成功", self.dbCursor)
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " " + self.msgHost + " ftp用户登录成功") except:
self.loginSuccess = 0
msgInsert(self.user, "error", "ftp用户登录失败", self.dbCursor)
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " " + self.msgHost + " ftp用户登录失败") # 检查ftp是否登录成功
def isLogin(self):
# return 1
return self.loginSuccess # 下载单个文件
def downLoadFile(self, LocalFile, RemoteFile):
curTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
# 如果本地有文件删除
if os.path.exists(LocalFile):
os.remove(LocalFile)
# 如果本地写入
try:
buffer_size = 1024 * 1024
file_handler = open(LocalFile, 'wb')
self.ftp.retrbinary('RETR ' + RemoteFile, file_handler.write, buffer_size)
file_handler.close()
msgInsert(self.user, "info", LocalFile + "写入本地成功", self.dbCursor)
print(curTime + " " + self.msgHost + " " + LocalFile + "写入本地成功")
self.isFileSuccess = 1 except:
msgInsert(self.user, "error", LocalFile + "写入本地失败", self.dbCursor)
print(curTime + " " + self.msgHost + " " + LocalFile + "写入本地失败")
self.isFileSuccess = 0 # 删除ftp文件
if self.isFileSuccess == 1:
try:
self.ftp.delete(RemoteFile)
msgInsert(self.user, "info", self.filepath + RemoteFile + "删除ftp文件成功", self.dbCursor)
print(curTime + " " + self.msgHost + " " + self.filepath + RemoteFile + "删除ftp文件成功")
except:
msgInsert(self.user, "error", self.filepath + RemoteFile + "删除ftp文件失败", self.dbCursor)
print(curTime + " " + self.msgHost + " " + self.filepath + RemoteFile + "删除ftp文件失败") return True # 下载整个目录下的文件
def downLoadFileTree(self, LocalDir, RemoteDir):
if not os.path.exists(LocalDir):
curTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
try:
os.makedirs(LocalDir)
msgInsert(self.user, "info", LocalDir + "本地目录创建成功", self.dbCursor)
except:
msgInsert(self.user, "error", LocalDir + "本地目录创建失败", self.dbCursor)
print(curTime + " " + self.msgHost + " " + LocalDir + "本地目录创建失败")
try:
curTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
self.ftp.cwd(RemoteDir)
RemoteNames = self.ftp.nlst()
msgInsert(self.user, "info", self.filepath + "切换目录和读取列表成功", self.dbCursor)
print(curTime + " " + self.msgHost + " " + self.filepath + "切换目录和读取列表成功")
except:
msgInsert(self.user, "error", self.filepath + "切换目录和读取列表失败", self.dbCursor)
print(curTime + " " + self.msgHost + " " + self.filepath + "切换目录和读取列表失败") for file in RemoteNames:
Local = os.path.join(LocalDir, file)
# print(file)
if file.find(".") == -1:
self.filepath += file + '/'
if not os.path.exists(Local):
try:
os.makedirs(Local)
msgInsert(self.user, "info", Local + "本地目录创建成功", self.dbCursor)
print(curTime + " " + self.msgHost + " " + Local + "本地目录创建成功")
except:
msgInsert(self.user, "error", Local + "本地目录创建失败", self.dbCursor)
print(curTime + " " + self.msgHost + " " + Local + "本地目录创建失败") self.downLoadFileTree(Local, file)
# 删除目录
self.ftp.rmd(file)
elif file.find(".") == 0:
pass
else:
self.downLoadFile(Local, file)
self.ftp.cwd("..")
# print('start')
# print(self.filepath)
self.filepath = self.filepath[0:self.filepath.rstrip("/").rfind("/")+1]
# print(self.filepath)
# print('end')
return def close(self):
self.ftp.quit() # 移植函数
def getSiteFtpFile(host, port, username, passwd, localDir, dbconn):
# dbconn = sqlite3.connect('getFile.sqlite3', check_same_thread=False)
try:
dbconn = pymysql.connect("127.0.0.1", "root", "root", "ftpwork")
dbCursor = dbconn.cursor()
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " " + host + " 连接mysql成功")
except:
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " " + host + " 连接mysql失败") ftp = myFtp(host, port, username, passwd, dbCursor)
isLogin = ftp.isLogin()
if isLogin == 1:
try:
ftp.downLoadFileTree(localDir, '/')
except:
msgInsert(username, "error", "ftp.downLoadFileTree方法执行中断", dbCursor)
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " " + host + " ftp.downLoadFileTree方法执行中断") ftp.close() print(time.strftime("########### " + "%Y-%m-%d %H:%M:%S", time.localtime()) + " " + host + " 执行完成 ###########")
# dbCursor.close()
dbconn.commit()
dbconn.close() # 自定义线程
class myThread(threading.Thread):
def __init__(self, threadID, name, host, port, username, passwd, localDir, dbConn):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.host = host
self.port = port
self.username = username
self.passwd = passwd
self.localDir = localDir
self.dbConn = dbConn def run(self):
print("开始线程:" + self.name)
getSiteFtpFile(self.host, self.port, self.username, self.passwd, self.localDir, self.dbConn)
print("退出线程:" + self.name) # 监控消息写入mysql
def msgInsert(msgHost, msgType, msgContent, dbCur):
datetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
dbCur.execute("INSERT INTO ftp_getfile (title,content,w_time,msgtype) \
VALUES ('" + msgHost + "', '" + msgContent.replace("\\","/") + "','" + datetime + "' ,'" + msgType + "')") if __name__ == "__main__": conn = ''
# 创建两个线程
thread1 = myThread(1, "Thread-1", "ftp_ip", 21, 'ftp_user', 'ftp_passwd', 'Z:/', conn)
# thread2 = myThread(2, "Thread-2", "ftp_ip", 21, 'ftp_user', 'ftp_passwd', "Z:/", conn)
# thread3 = myThread(3, "Thread-3", "ftp_ip", 21, 'ftp_user', 'ftp_passwd', 'D:/root-python/test/03', conn)
# thread4 = myThread(4, "Thread-4", "ftp_ip", 82, 'ftp_user', 'ftp_passwd', 'D:/root-python/test/04', conn)
# thread5 = myThread(5, "Thread-5", "ftp_ip", 21, 'ftp_user', 'ftp_passwd', 'D:/root-python/test/05', conn)
# thread6 = myThread(6, "Thread-6", "ftp_ip", 82, 'ftp_user', 'ftp_passwd', 'D:/root-python/test/06', conn)
try:
# 开启新线程
thread1.start()
# thread2.start()
# thread3.start()
# thread4.start()
# thread5.start()
# thread6.start() thread1.join()
# thread2.join()
# thread3.join()
# thread4.join()
# thread5.join()
# thread6.join() except:
print("Error: unable to start thread") # while 1:
# pass

Python脚本通过ftp协议移植文件的更多相关文章

  1. 一个ftp协议传输文件之后执行脚本无法工作的情况

    作者:良知犹存 转载授权以及围观:欢迎添加微信号:Conscience_Remains 总述         移植一个文件系统时候,我在window下git clone了对方仓库源码,然后用FileZ ...

  2. vsftpd-基于ftp协议的文件传输服务器软件

    第一部分:在Linux上部署vsftpd服务 1. vsftpd简介 1.1 vsftpd是什么? ftp(File Transfer Protocol)文件传输协议.(实现不同操作系统之间文件的传输 ...

  3. Shell脚本调用ftp上传文件

    Shell脚本调用ftp上传文件 1.脚本如下 ftp -n<<! open x.x.x.x ###x.x.x.x为ftp地址 user username password ###user ...

  4. Python脚本打包成exe执行文件

    需求 一个教辅目录结构检查工具,目录结构是[书籍]-[章节]-[题目|答案]-[*.jpg],后台有个异步处理的服务,需要强依赖这个目录结构. 书籍解析是单独的pipeline,日志对用户不可见,这里 ...

  5. 开发错误日志之FTP协议传输文件问题

    从开发端用FTP协议向服务器(Linux系统)传输文件时,cat -A查询文件内容中行尾会有^M出现. 解决方案:改用SFTP协议上传文件.

  6. linux脚本:ftp自动传输文件

    使用Shell脚本实现ftp的自动上传下载 http://liwenge.iteye.com/blog/566515 open 192.168.1.171 user guest 123456cd /h ...

  7. ubuntu下把python脚本转为二进制字节码文件

    ubuntu下把python脚本转为二进制字节码文件 听语音 原创 | 浏览:354 | 更新:2017-12-22 14:48 1 2 3 4 5 6 7 分步阅读 自己拥有个几个python脚本文 ...

  8. python网络编程--FTP上传文件示例

    1.基础版(供学习了解原理使用,low) server服务端 import socket import struct import json server = socket.socket() ip_p ...

  9. python脚本-excel批量转换为csv文件

    pandas和SQL数据分析实战视频教程 https://study.163.com/course/courseMain.htm?courseId=1006383008&share=2& ...

随机推荐

  1. 理解C/C++的复杂声明

      理解C/C++的复杂声明        曾经碰到过让你迷惑不解.类似于int * (* (*fp1) (int) ) [10];这样的变量声明吗?本文将由易到难,一步一步教会你如何理解这种复C/C ...

  2. docker ps 显示指定的列

    可以自己指定显示的模板,例如: docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}" table - 表示显示表头列 ...

  3. RobotFramework+Appium 为了兼容iOS12,升级至Xcode10后,WebDriverAgent编译不通过:Undefind symbols for architecture x86_64

    报错信息如下: Undefined symbols for architecture arm64: "_OBJC_CLASS_$_XCElementSnapshot", refer ...

  4. 多线程之美7一ReentrantReadWriteLock源码分析

    目录 前言 在多线程环境下,为了保证线程安全, 我们通常会对共享资源加锁操作,我们常用Synchronized关键字或者ReentrantLock 来实现,这两者加锁方式都是排他锁,即同一时刻最多允许 ...

  5. CodeForces - 786B -- 线段树优化建图

    刚开始想了两个小时,打算把区间分块然后计算,但是这就很灵性了看了一个大佬的博客,侵删 #include<cstring> #include<iostream> #include ...

  6. C# 字符串与二进制的相互转换

    /// <summary> /// 将字符串转成二进制 /// </summary> /// <param name="s"></para ...

  7. 20191010-7 alpha week 1/2 Scrum立会报告+燃尽图 06

    此作业参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8750 小组名称:“组长”组 组长:杨天宇 组员:魏新,罗杨美慧,王歆瑶,徐丽 ...

  8. 电脑端TIM登录时记住密码

    为什么每次登录TIM时点了记住密码,下次再登录时还是记不住呢? 不是扫码就是还得输出密码,为这事愁了好多次, 最近终于发现如何记住密码了... 进入登录界面以后,点击左下角这个小图标>> ...

  9. 10道java经典算法题,每一题都能帮你提升java水平!

    JAVA经典算法题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析:   ...

  10. JVM系列(三):java的垃圾回收机制

    java垃圾回收机制介绍    上一篇讲述了JVM的内存模型,了解了到了绝大部分的对象是分配在堆上面的,我们在编码的时候并没有显示的指明哪些对象需要回收,但是程序在运行的过程中是会一直创建对象的,之所 ...