从配置文件读取参数,每周定时执行:停止程序,备份数据,重启程序。
# -*-coding: GBK -*-
import psutil
import os
import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
import shutil
import time
import threading
import subprocess
import schedule
import asyncio
# 全局变量:配置文件
glob_config = "config_p.txt"
def txt_to_dict(filename):
with open(filename, 'r', encoding='utf-8') as f:
data_dict = {}
for line in f:
# 忽略空行和注释行
if line.strip() == '' or line.startswith('#'):
continue
key, value = line.strip().split('=')
data_dict[key] = value
return data_dict
def txt_to_dict_l(filename):
with open(filename, 'r', encoding='utf-8') as f:
data_l = []
for line in f:
# 忽略空行和注释行
if line.strip() == '' or line.startswith('#'):
continue
key, value = line.strip().split('=')
if 'exe' in value:
data_l.append(value)
return data_l
def check_pid(process_path_pattern):
# 获取所有运行中的进程
all_processes = psutil.process_iter()
# 存放pid
pid_l = []
# 遍历并打印每个进程的信息
for proc in all_processes:
if proc.name() == 'spe_post.exe':
try:
# 获取进程名称、PID和程序位置
process_name = proc.name()
process_id = proc.pid
process_path = proc.exe()
for ppp in process_path_pattern:
# 判断两个路径是否相等,匹配spe程序
if os.path.normcase(process_path) == os.path.normcase(ppp):
# 获取进程id
pid_l.append(process_id)
# 打印进程信息
# print(f"Process Name: {process_name}")
print(f"进程PID: {process_id}")
print(f"进程路径: {process_path}")
print("-----")
else:
print(f"*****运行中的该spe程序不在配置文件当中*****")
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass # 忽略无法访问或已终止的进程
# print(pid_l)
return pid_l
def kill_process_by_pid(pid):
try:
# 获取进程对象
process = psutil.Process(pid=pid)
# 终止进程
process.kill()
print(f"*****进程PID: {pid} 已经被终止运行*****")
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass # 忽略无法访问或已终止的进程
def stop_process():
# 读取配置文件,获取spe程序的绝对路径
process_path_pattern = txt_to_dict_l(glob_config)
# 获取运行中的spe程序pid
pid_l = check_pid(process_path_pattern)
if pid_l:
for pid in pid_l:
# 调用函数结束进程
kill_process_by_pid(pid)
else:
print(f"*****当前无匹配的spe程序运行*****")
# 等待10秒
time.sleep(10)
current_time = datetime.datetime.now()
print(f"*****当前时间:{current_time},终止spe程序,执行完毕*****")
# return "停止spe程序,执行完毕"
def move_file():
# 读取配置文件,获取spe程序的绝对路径
process_path_pattern = txt_to_dict_l(glob_config)
# spe程序下需要移动的5个文件
move_file = ['data.ssr', 'move.pos', 'move.raw', 'nav.raw', 'out_los.txt']
# 读取配置文件,加载字典
data = txt_to_dict(glob_config)
# 获取特定键值对的值,指定父目录的名称
parent_dir = data.get('parent_dir', 'null')
# 指定子目录的名称
now = datetime.datetime.now()
child_dir = str(now.strftime('%Y%m%d-%H%M%S'))
# 拼接子目录的完整路径
child_dir_path = os.path.join(parent_dir, child_dir)
# 创建子目录
os.makedirs(child_dir_path, exist_ok=True)
# 获取spe程序的上层目录
for path_dir in process_path_pattern:
# 获取文件的文件夹路径
src_path = os.path.dirname(path_dir)
# 重命名备份的文件夹名称
if "PROD_V2_N" in src_path:
print("*****PROD_V2_N环境的SSR文件*****")
cchild_dir = "PROD_V2_N"
elif "PROD_V2" in src_path:
print("*****PROD_V2环境的SSR文件*****")
cchild_dir = "PROD_V2"
elif "PROD" in src_path:
print("*****PROD环境的SSR文件*****")
cchild_dir = "PROD"
elif "TEST_V2_P" in src_path:
print("*****TEST_V2_P环境的SSR文件*****")
cchild_dir = "TEST_V2_P"
elif "TEST_V2" in src_path:
print("*****TEST_V2环境的SSR文件*****")
cchild_dir = "TEST_V2"
elif "TEST" in src_path:
print("*****TEST环境的SSR文件*****")
cchild_dir = "TEST"
else:
print("*****非PROD和TEST环境的SSR文件*****")
cchild_dir = "NN"
# 拼接子子目录的完整路径
cchild_dir_path = os.path.join(child_dir_path, cchild_dir)
# 创建子子目录
os.makedirs(cchild_dir_path, exist_ok=True)
for file in move_file:
# 获取文件的完整路径
src_file_path = os.path.join(src_path, file)
# 获取目标路径
dst_file_path = os.path.join(cchild_dir_path, file)
# 判断文件是否存在
if os.path.exists(src_file_path):
# 移动文件
shutil.move(src_file_path, dst_file_path)
# print(f"移动文件完成:", dst_file_path)
time.sleep(5)
# 等待10秒
time.sleep(10)
current_time = datetime.datetime.now()
print(f"*****当前时间:{current_time},移动文件,执行完毕*****")
# return "移动文件,执行完毕"
def restart_process():
# 读取配置文件,获取spe程序的绝对路径
process_path_pattern = txt_to_dict_l(glob_config)
# 执行可执行程序
for executable_path in process_path_pattern:
# 获取spe程序的文件夹路径
exe_path = os.path.dirname(executable_path)
# 先切换到spe程序的所在目录,再执行start启动命令
cmd1 = 'cd' + ' ' + exe_path
cmd2 = 'start spe_post.exe'
os.system('%s && %s' % (cmd1, cmd2))
# subprocess.run([executable_path])
# 等待10秒
time.sleep(10)
current_time = datetime.datetime.now()
print(f"*****当前时间:{current_time},重启spe程序,执行完毕*****")
def run_threading():
# 创建线程并启动停止spe程序、移动文件、重启spe程序
job_stop_process = threading.Thread(target=stop_process)
job_move_file = threading.Thread(target=move_file)
job_restart_process = threading.Thread(target=restart_process)
# 启动线程,等待停止spe程序执行完成后,再移动文件,最后重启spe程序
job_stop_process.start()
job_stop_process.join()
job_move_file.start()
job_move_file.join()
job_restart_process.start()
job_restart_process.join()
# async def main():
# # 等待程序1执行完成后再执行程序2
# result1 = await stop_process()
# result2 = await move_file()
# print(result1)
# print(result2)
#
# # 运行主程序
# asyncio.run(main())
if __name__ == '__main__':
# 读取配置文件,加载字典
data = txt_to_dict(glob_config)
# 获取运行时间
run_time_daily = data.get('run_time_daily', '08:10')
run_time_weekly = data.get('run_time_weekly', 'mon')
# 拆分运行时间为小时和分钟
rt = run_time_daily.strip().split(':')
ht, mt = int(rt[0]), int(rt[1])
current_time = datetime.datetime.now()
print(f"*****当前时间:{current_time},开始执行任务*****")
# 创建调度器
scheduler_weekly = BlockingScheduler()
# 添加定时任务,使用cron表达式,表示每周的(mon,tue,wed,thu,fri,stat,sun)的ht:mt时刻执行一次
# scheduler_weekly.add_job(run_threading, 'cron', week='*', day_of_week=run_time_weekly, hour=ht, minute=mt, second=0)
# 添加定时任务,使用interval表达式,表示每间隔5秒执行一次
# scheduler_weekly.add_job(run_threading, 'interval', seconds=5)
# 添加定时任务,使用interval表达式,表示每间隔5分钟执行一次
scheduler_weekly.add_job(run_threading, 'interval', minutes=60)
# 开始调度器
scheduler_weekly.start()
config文件如下:
# 每周执行任务(停止spe程序&备份数据&重启spe程序)-北京时间 # 小时&分钟 run_time_daily=15:01 # 可选mon,tue,wed,thu,fri,stat,sun分别表示星期一、二、三、四、五、六、日 run_time_weekly=thu # spe程序的路径,默认test、test_p、prod、prod_n四个环境,若停止监控该环境,只需将该值置空或注释掉 #origin_path_test=E:/python/pythonProject1/threading_test/N_TEST_20231105.pos origin_path_test=E:/data/PROD/sppost.exe origin_path_test_p=E:/DPI/路测/0925版本SPE/sppost.exe #origin_path_prod=E:/python/pythonProject1/threading_test/N_PROD_20231105.pos #origin_path_prod_n=E:/python/pythonProject1/threading_test/N_PROD_20231105.pos # 备份文件的路径 parent_dir=E:/data/备份