在本地修改文件后希望自动上传到服务器(Ubuntu)上去,于是写了一个py程序。因为电脑是win10系统,所以使用了Putty自带的
pscp.exe
来执行,具体实现的代码如下(用户名及密码需要自行设置):
这个py文件改了很多次,所以代码中会发现有些数据在几个变量名之间转手了好几次,就是因为修改的时候老的代码不想管了,增加了新的变量及相关代码,等新代码处理完以后又把新变量的值传递给老的变量。感觉有点像动物的基因,都是在原来的基础上修修补补,例如人类的视网膜,因为演化的时候反复折叠,所以成了现在这个样子:光线在到达感光细胞之前还要先穿过视神经和血管,导致我们在白天看天空这种亮背景时就可以看到有许多很小很小的小亮点在快速移动,一会儿出现一会儿小时的;还导致了每只眼睛都有一个视觉盲点,因为视神经需要在视网膜上开个洞钻出眼球。。。
- 本py文件可以先扫描一次自己所在的文件夹中的文件,包括子文件夹里的文件,记录文件的最后修改时间作为初始值
- 每隔一定时间再扫描一下本地文件的修改时间,发现修改时间改变了的就上传到服务器上去
- 如果本地文件被删除了,不会影响啥子,但是:无法同时删除服务器上的文件,服务器上的文件需要手动删除
- 如果本地文件增加 了,本程序无法发现 新增的文件,需要手动重启本py并且把新增的文件再保存一次(改变其最后修改时间)
- 我安装了
Putty
,使用其自带的pscp
命令上传文件,这个命令可以把用户名密码也一起写上去
实现代码如下
需要自行提供服务器相关信息
# ===============================================================
# 这个py文件用于:通过监控硬盘文件的修改时间是否变化,自动把修改后的文件通过pscp命令上传到服务器上去的,免得我每次都要用命令上传,好麻烦哦(本来可以用FTP客户端绑定修改后上传的,但是忘记怎么设置了,懒得去弄了,直接写个这个算了!)
# 初始扫描后,文件不会上传,要重新保存果一次后,才开始上传
# ===============================================================
import os # 系统模块,调用dos命令、查看文件修改时间
import time # 无限循环的暂停时间(按 Ctrl+C 终止运行)
import re # 正则
# ★★★★★★★★★★ 需要用户自己设置(以下) ★★★★★★★★★★
# 服务器ssh登录信息
ip = '127.0.0.1' # 服务器IP地址
usn = 'username' # linux上的用户名
pw = 'password' # 用户的密码
# 设置服务器上的文件夹路径,以用户的家目录作为起点(不设置本地路径,本地路径是当前py文件所在的路径)
server_path = 'web/site1/' # 开始不加/,最后要加/
# 无限循环的暂停时间(监控扫描文件的间隔时间,秒钟)
stop_second = 3
# 例外文件清单,不上传比如密码文件啊啥子的(另:以 _ 和 . 开头的文件默认不处理)
file_exclude_list = []
# ★★★★★★★★★★ 需要用户自己设置(以上) ★★★★★★★★★★
# 获取当前这个py文件名字(后面上传时判断用,这个文件不用上传)
osps = os.path.split(__file__) # for获取当前文件名
nameofmyself = osps[1] # 获取当前文件名
# 取得本地路径:这个路径下的所有文件都要被监控,一但修改就上传上去
# 以当前这个autoFTP.py文件所在文件夹为起点,查询其下的文件们,形成待上传文件初始列表
# local_path = os.getcwd().replace('\\', '/') + '/' # cwd返回的斜线是\,会被识别成转义字符的,cwd返回的{工作路径},不是py文件的路径
local_path = os.path.dirname(os.path.abspath(__file__).replace('\\', '/')) + '/'
# 监控文件列表
filelist = [] # 待上传文件信息列表,将来用来替换auto_upload_files的
# 读取当前路径下的文件并加入到filelist列表中去
def add_files_into_list(path, serverpath):
# 本函数中的 filelist 系指全局变量 filelist
global filelist
# 获取path路径下的文件名、文件夹名
files = os.listdir(path)
for str_filename in files: # 循环处理
# 如果就是当前文件,那么就不处理了:当前py文件就不要再上传啊!
if str_filename == nameofmyself:
continue
# 看当前名称是不是文件夹: 如果名称没有小数点,就识别为文件夹
is_folder = True if re.match(r'^[\w\.\+-=\s]+[\.][\w\+-=\s]+$', str_filename) is None else False
if is_folder: # 如果是文件夹
# 不处理 以 . 或者 _ 开头的文件夹(缓存文件等)
if re.match(r'^[_\.]', str_filename) is None:
folder_name = str_filename + '/'
# print('%s, %s' % (path + folder_name, serverpath + folder_name))
# 递归调用
add_files_into_list(path + folder_name, serverpath + folder_name)
else: # 不是文件夹,则直接处理即可
if not (str_filename in file_exclude_list):
filelist.append({
'f': str_filename,
'l': path,
's': serverpath,
't': os.stat('%s%s' % (path, str_filename)).st_mtime
})
# [
# {"f": "chart.htm",
# "l": "D:/py/site1/",
# "s": "web/site1/",
# "t": 最后修改时间的值}
# ]
# 调用函数,生成 filelist 列表
add_files_into_list(local_path, server_path) # local_path自动获取, server_path用户设置
# print(filelist)
# 将监控文件列表传给auto_upload_files
auto_upload_files = filelist # 把生成的列表转给原来写的变量
# 打印监控文件列表函数
def print_auto_upload_files():
print('-' * 80)
print(' # 本地文件根目录 = %s' % local_path)
print(' # 服务器根目录 = %s@%s:[home/]%s' % (usn, ip, server_path))
print(' 监控下列文件并自动上传(时间间隔%d秒):' % stop_second)
i = 1
for ob in auto_upload_files:
print(' (%d) %s%s => %s@%s:%s' % (i, ob["l"], ob["f"], usn, ip, ob["s"])) # 打印受监控的文件信息
i += 1
print('-' * 80)
print(' 文件监控中(按Ctrl+C退出) ... <如果有新增文件,请重启本py文件>')
# 打印监控文件列表
print_auto_upload_files()
# 无限循环,每stop_second秒钟循环一次
upload_count = 0 # 上传的次数,计数器
while True:
# 是否有上传? 要是有的话,最后要输出一个横线,初始化为没有
upload_done = False
# 是否重新打印监控目录,如果有文件被删除了,需要重新打印.初始化为不用
reprint_filelist = False
# for循环列表中的每一个文件
auto_upload_files_index = 0 # 监控文件列表的索引号
for file_a in auto_upload_files:
# 试着读取文件修改时间
try:
# 先试着读取一下这个文件的修改时间,如果这个文件被删除了就可能出错
newest_file_time = os.stat('%s%s' % (file_a["l"], file_a['f'])).st_mtime
except Exception as e:
# 如果文件或者文件夹被删除了,这里会提示错误
print(' # [文件被删除][%s] %s' % (file_a['f'], e))
# 从auto_upload_files中删除这个文件的信息
auto_upload_files.pop(auto_upload_files_index)
# print(auto_upload_files)
# upload_done = True # 也输出一条横线好了
reprint_filelist = True # 重新打印监控文件目录
continue # 接着处理监控列表中的后续文件
if newest_file_time != file_a['t']: # 那么就说明是修改了的
# 记录dos命令pscp成功与否的变量,成功==0,其他!=0
r = -1
# 循环上传,有时候上传要失败
while r != 0:
r = os.system('pscp -pw %s %s%s %s@%s:%s' % (pw, file_a['l'], file_a['f'], usn, ip, file_a['s']))
yyyymmdd_hhmmss = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) # 当前时间
# 如果上传成功,更新监控列表{}对象中的t的键值
if r == 0:
# 计数器+1
upload_count += 1
# 上传成功后,for循环结束时要输出一条横线
upload_done = True # 后面要输出一条横线
# 更新时间记录
file_a['t'] = os.stat('%s%s' % (file_a['l'], file_a['f'])).st_mtime
# 提示成功
print(' [%d] 文件 %s 上传成功! %s' % (upload_count, file_a['f'], yyyymmdd_hhmmss))
# 如果上传失败,提示,然后继续上传
else:
print(' 文件 %s 上传失败!正在尝试重新上传... %s' % (file_a['f'], yyyymmdd_hhmmss))
else:
# 如果没修改,就不处理
pass
# auto_upload_files的索引号+1
auto_upload_files_index += 1
# 输出一根横线
if upload_done:
print('-' * 80)
print(' 文件监控中(按Ctrl+C退出) ... <如果有新增文件,请重启本py文件>')
# 重新打印监控文件目录
if reprint_filelist:
print(' # 监控文件调整为:')
print_auto_upload_files()
# 间隔5秒钟
time.sleep(stop_second)
网友评论