-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.py
More file actions
178 lines (144 loc) · 4.8 KB
/
main.py
File metadata and controls
178 lines (144 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# -*- coding: utf-8 -*-
"""
GitHub Hosts 自动更新服务主程序
使用APScheduler调度器每小时自动检查GitHub hosts是否变化,如有变化则更新本地hosts文件
"""
import sys
import os
import ctypes
import logging
from pathlib import Path
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.interval import IntervalTrigger
from config import (
LOG_FILE, LOG_FORMAT, LOG_DATE_FORMAT, LOG_MAX_BYTES, LOG_BACKUP_COUNT,
CHECK_INTERVAL_HOURS
)
from hosts_updater import check_and_update
logger = logging.getLogger(__name__)
def is_admin():
"""
检查当前程序是否以管理员权限运行
Returns:
bool: True表示有管理员权限
"""
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def run_as_admin():
"""
以管理员权限重新启动程序
"""
try:
if sys.argv[-1] != 'asadmin':
# 使用ShellExecuteW以管理员身份重新启动程序
ctypes.windll.shell32.ShellExecuteW(
None,
"runas",
sys.executable,
f'"{__file__}" asadmin',
None,
1
)
sys.exit(0)
except Exception as e:
print(f"无法以管理员权限启动程序: {e}")
print("请手动以管理员身份运行此程序")
input("按回车键退出...")
sys.exit(1)
def setup_logging():
"""
配置日志系统
"""
# 创建日志目录
log_file = Path(LOG_FILE)
log_file.parent.mkdir(parents=True, exist_ok=True)
# 配置日志格式
formatter = logging.Formatter(LOG_FORMAT, LOG_DATE_FORMAT)
# 文件处理器(轮转日志)
from logging.handlers import RotatingFileHandler
file_handler = RotatingFileHandler(
LOG_FILE,
maxBytes=LOG_MAX_BYTES,
backupCount=LOG_BACKUP_COUNT,
encoding='utf-8'
)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.INFO)
# 控制台处理器
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
console_handler.setLevel(logging.INFO)
# 配置根日志器
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
root_logger.addHandler(file_handler)
root_logger.addHandler(console_handler)
logger.info("日志系统初始化完成")
def scheduled_check():
"""
定时检查任务函数
"""
try:
logger.info("=" * 50)
logger.info("开始执行定时检查任务")
success, message = check_and_update()
if success:
logger.info(f"检查完成: {message}")
else:
logger.error(f"检查失败: {message}")
logger.info("定时检查任务执行完毕")
logger.info("=" * 50)
except Exception as e:
logger.error(f"定时检查任务执行异常: {e}")
def main():
"""
主程序入口
"""
print("GitHub Hosts 自动更新服务")
print("=" * 40)
# 检查管理员权限
if not is_admin():
print("检测到程序未以管理员权限运行")
print("正在尝试以管理员权限重新启动...")
run_as_admin()
return
print("管理员权限检查通过")
# 设置日志
setup_logging()
logger.info("GitHub Hosts 自动更新服务启动")
logger.info(f"检查间隔: {CHECK_INTERVAL_HOURS} 小时")
logger.info(f"日志文件: {LOG_FILE}")
# 立即执行一次检查
logger.info("执行启动时检查")
scheduled_check()
# 配置调度器
scheduler = BlockingScheduler()
# 添加定时任务
scheduler.add_job(
func=scheduled_check,
trigger=IntervalTrigger(hours=CHECK_INTERVAL_HOURS),
id='github_hosts_check',
name='GitHub Hosts 检查任务',
replace_existing=True
)
logger.info("调度器配置完成,开始运行...")
print(f"服务已启动,将每 {CHECK_INTERVAL_HOURS} 小时检查一次")
print("按 Ctrl+C 停止服务")
print("=" * 40)
try:
# 启动调度器
scheduler.start()
except KeyboardInterrupt:
logger.info("收到停止信号,正在关闭服务...")
scheduler.shutdown()
logger.info("服务已停止")
print("服务已停止")
except Exception as e:
logger.error(f"调度器运行异常: {e}")
print(f"服务运行异常: {e}")
finally:
print("程序退出")
if __name__ == "__main__":
main()