From ecb30f7aa10da7fa11f428a922849e0d44baf1cc Mon Sep 17 00:00:00 2001 From: ui-beam-9 Date: Tue, 29 Apr 2025 22:24:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83=E6=96=B0=E7=89=88=E6=9C=ACv2?= =?UTF-8?q?0250429213045?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- download_auto_run.py | 553 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 509 insertions(+), 44 deletions(-) diff --git a/download_auto_run.py b/download_auto_run.py index b599db2..b6363ed 100644 --- a/download_auto_run.py +++ b/download_auto_run.py @@ -1,49 +1,514 @@ +#!/usr/bin/env python # -*- coding: utf-8 -*- -import base64,zlib,sys,os,time,random -import threading,importlib,subprocess -def _XpdtICfJk6fG(d,k): - return bytes(a^b for a,b in zip(d,k*(len(d)//len(k)+1))) +""" +Python 2.7 Auto Download Script +For NetEase Da Shen Review Data Monitoring System +""" -def _nLblj46p1(t,m,is_error=False): - try: - try: - from playsound import playsound - except ImportError: - subprocess.check_call([sys.executable,"-m","pip","install","playsound==1.2.2"], - stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) - from playsound import playsound - - # 播放系统声音 - try: - import winsound - sound_type = winsound.MB_ICONERROR if is_error else winsound.MB_ICONINFORMATION - winsound.MessageBeep(sound_type) - except: - print("\a") # 备用蜂鸣声 - - # 在控制台打印消息 - print("\n" + "="*50) - print(f"{t}: {m}") - print("="*50 + "\n") - - return True - except Exception as e: - print(f"\n{t}: {m} (提示音播放失败: {str(e)})\n") - return False +import os +import sys +import time +import shutil +import urllib2 +import getpass +import base64 +import subprocess +import traceback +import codecs +from datetime import datetime -def _PptF7lliKBC(t,m,e=0): - _nLblj46p1(t,m,e==1) - -# 直接执行解密和运行代码 -_SeRxUx=b'u \xd5\xa7\x98w\xcen\xd4\x14\x89\xd6\xa8\x99\xb8\xc7' -_QYb3wBdh=b'4ZJv;^CZ=&Ld$&pPP6^ysGucGehp`w(@T=^25S=stjzd40&Qx4m^MVd&)V3SFGL12wGkB4@^oY-%<0*5dJXOGipNlkylrdaMYDw&`=_$7K!h$b632N)NghFXg6VeJu9~Ys=|hbFsDqso=U5gu#1>mfA;9TcB|On6TBY45A$evIuw5eqHOM`A+}uPaz^IPvcXZ3?9)~7~-YRE~mLZ%$$Rb{jEJMEuMRsQ>M}=b%s3xO4fZCf!i-4Bj5!kXBZi)+?Wm9F31KA3(EMbpXfZ9ZKM!=9yP4%Oe3ve&WpZx=mO(8;VzD%1qE|lD0P0)(~=Yg+Wb^zb=MWb9>OlPKSsGPH_OPz`QWx;pX4XplS*76i_i~7zOMGG=AJwRhwo+ULd8wJ+P_PbydpL-Mi<40p`Xewo611w+z3FFrYSq5dEhek`?!_*ZWL#CjT;|9Vp!CE0x|ImQ)>S&$blOBOwJVS&I>~?n&ZIoa2(-D0YG=bket3$2_qBY*n>6sZAxA@fjPskb*xDd%8n3(eVhv_sF$|oS>)QhI=39y@p@zI^rILUOq!MN-mg$}5rx0}toxFQYu6dy*@@c99(k(=M?|0Z<~Fgd!>S2_w;%P@7Si}70|zEvhZ&e)GM^Ug7$tYGgZtOHMnd1}^A9`bU-6M?P!iAaCo$4}Sj4SQl5DY`VHF+j-qf+^^7dAo_cOhh_C;TGxe(E&m%gxWBI{7fGu3$`g4uhUyLSIFSLK<|@k^u+kNMj(g7ICJI8_S6qShd*M^9-a$1Ef9wReO(Xe;s{1g{d55ES((zd=2$Mtdt5YRxs--uq1uZVP@TI7K;*5z1i9q&cL2-;IB32`;|pca{=2=%;fO#~aV#@05(WrSPq}y;vrovsQ#}JJ5m%1*!c)=1eQ*)%8V6q;>0WSZp?H|yncZ98O1Jgl>7st0j%MHqS#QJ-9oXB8q1_{}>v(1QT^%yiPv|Hk5#9;ymc7!j~$^u)ddC7+wzQP9P3W99l|zM$?cY`$$QXB;Mi(HxC`zK4&?#K7y+xy|b7I_?eAnaCRC$0*=fa^jYUSW#>;PEm`P;pebgI)$kx_rOLCZn~O{Ma|S&WkJ=v{Z@O)W4r^ZkpDyQ%L$~`}wagLO0~fyxD>s#c0b6++8w>r4~YL_-9WtBOJGKv)N$I5dMvs_KF!7Wmo{pWagtrrflcT0vgrOJ@)@@rwq*&7^8}i_V5M`EPd{FYTL#UTXoL6Yj)Rt*Tg~>&+Et~2di2(k67VMIP?Q3(Y6e8inn`*u^ooRyFq6M1ls$`NSyjK3ebVw_>}B{=!QcI&#?wGdh$JxAp8?7^0VzGHClN3WaA3?a1bSRfD%Byf8aN>v-%aNSSkqoJ8Zr)cy8<&86KBeKOV9xmqO5)bS<0s{UIAP-wLJNSC|g8m~(Y=9^q%2=Qy|G51aV$skovJ`o@OOn5whM{vJQQ-8n_?yWGa(mY0|`!F<2;S@MKDelX=Rim-X6cgY$rQY%OmE~DFvJIBMNozL0^jcSJTGJlSFr`OvBdh&VJ<*PHET&@hj>pAw>tUO1()Zg=Eri1xZehu4(kAemup3S6_w4WqKZM)61raf_T|xb$y*{#74(QtzN!s;|_J7H^)yKVRS?Ip_a?!rsVXu2gCj@O9zG*JVLR3#k}Oldi5Won38R?7SnEB1#A$KXVOd6$7snqqzchBZQcv0IAfXipJ&s0#NNe)RgqmkyKzX(_0X&2rcRHI?(VwTv`AMlrS{rQ`lqXUAb@#Oi?RBCvN{3YEEJGbCIM(KG?chxQc|B+6fxRNzeV0c;EKktKX+cWOlDjplM>{>!TgNc<2fRbngNUnWSav*t;@BsOUSNEX9@3B&5Ae$M#nhUSl5l`nQ~seFhCE6S<8M%)pGS2*U8F!%B)#H75eB#(J7XP_6nKiTI+V_obH}?t;jW$IkafT)}xsz71!|r?j(KismjDDz5$T~XDe#`RfU_DpdWmBO8P6&8k|n25J4k1A@?hZ0jN{(c${FaK@`P^{_@S3t4xI$*+Ure{r*t}Ut>>zIK!1DDT*Hz!x&r+}D{Ur~YYx}t15;l1?+^Pco)Hh$9t%ErP!NkS0o9^x);i88(qEIP*(C1`0iA6{TAw&=!FOkcShCeSSi+yxeZzzrLFPiZ^Xu9%JWbBM+|*o^tqgNK!3N7A5IvPhd7AW(4UFi)dD%p{xprls7Badc+vS@8J8AvhKvx$B%&%KzzU>JfLI2lEwS=5+I0qXcHFgeW(zgokVjhi$k-rv5^A0K*!g8}`$kjruLs%%6-PB{zKA9-hXVx>%208`^;^~(UOl;?2?(Y*CBcm)?WBOkJ&SZ)CB9z{pl0XjGg6C=3p?}5x@T|EDN8j<*-uE;!!|l%|2Naz*NS(o+Ia^%v6E)Bud+{q;q4E()e58ypEnHOEMB^l-zQ>xbR$qcPpdAp70aq~!61MIRX7S=w+XN?tKoqqIT*}Xi+|TMN6oEblh7%{@8#QK*$}F#(g_=pyQJ7fC7Z;7|cvy5dq|1qG$fCQLAtSNYl%6z_$pZ6;o_|_hDsn{T$Q%>>XCzVLB@YC`dFoHs9$!xhzQ1u+e~KFwk@cd0(Ya|06LZy@gm!|y90{MHgT=ANprO%PtTDe2zUfayt)CjU?1B8k2R`L-u*B`w^D{|So~|dU3ZI>2juUS@i}eS9fF-fbofyTX7uYE;=~FQ@KbD$LD}L(0xu^7Z0k)kOa>}uC1z(-zk@pIexf%j8o3*a_Vyy;UqhrwvhAGKPtY`;S6gN^gS-sBv!9zvAi#0rQa{^f4(zIg)fT6j-~f&kLrjU0rq<4iVs`5;5Ij5(w|*O=0p@^f1@)DyY2oFtk_`^)?BFThgn$^P8Kfucq^X(3CXTz!@&H%1$nNdI(0&Po{2?)wa#F4kg*!o+xI7Qx?LPk7fr@PC^{lu}#DH1k5=DsCJfwUS^lGrf&^wd-2#;<}hRt3D(qzdsE|k4@~Y_GQ@7{oqjs9*5=Gk15PIX8aflPRcLe{6f5;jBeL*x42)AS9YaDB`*<#xLmxGhQR@c#(^oJy02~`QT>(vOmp$UqO|)P>(>u7LQPF5e^eQ#bS2p*1RC!EDdq2Bs*$g%fbOSvbeuau`_v}?s0<-ttBs3ez9ZsvSqaci2y-gi@$xR9moJLf+*E3t{BDhQA@BKS9kYa8l`U_I+Prf|2r?fF(>!ruWXJCG*kE;JPuz=*8C>saddhh=3W)7g!1OP_G8)KzEp9=Eff&4Yw*IF4!9d!{%Dq=>!&btH`yMlRbKJz-dJ~uZfiCiO{9n%{FB+GdGuA5%`^JKHScSMOwQm$D@Huykt`#_DT@eQ!~M{4K)~*I&&+F@bwIJ_@}I@q(Hj13B@;;xG#b8!PO!c(k##{k@`0t1nZKtvA|R2Ve^G4byJ8)lLe~%yn9#orvKzwM^br<{S;PIxQe-W9X4fw6M7kC#wqqapwlB}pSio5jCNZrR^p#(ipseq2aEEB&)ML5peGOwGsxSmerP)6yu%u34ldaF4QD7aA6+Q>tS}T(I3WWNh1|Iiq^KoQSg4|TD60x{76eUtj4~7~)iXm@E;E=F9UJF8^zschAdalBqVCYK~=bv`|Z)=F!RPX=HwtkDG<3!a02$&?gN~yvouUmJb9i$J3zFPcVGwV^49x!Pl<6sRzT)d`@`t`ZqdTbmZE-e(jU42e7Di^+(kRe}OGR(#b_5CJx|$I)M2Cp!{7c-wM8kt{&IPV)IwG4_l_t9E`kw={5M_gP>>*}6?kt*5@G24*MU@X&XLN9xuz4}D#y~F`L}XFe)cIK9*Ip&iYO#FXuP=BI9Zbz>vah?VlCtuY=JGwjAwx*QKTod?VS=awH%jy%y&%_(*A?d@!!R?D)~V5L*-#_6@J^~n^M8*!{;W@oZNHA=gusKPzZ$gXC&aR=thA_MdT+}aQ>W2o!$RFCdfQ}1Vp^Fgg#9eNf?ZF<)8d3Cd28wG6G~2a*RPDZG@9gW8D}&O;GS&J!Jy4y^MwXfgmA0d$O($y5pn{^cY7DRy(`t+eY1;fi{jhNRMSi2EQ<#3GQJ@wg2v+BVcx4gM(r1jI|ADqWALm2_PczRcY}~GXjkpm@&!x}&=(6A#AjH*=TMthHH>sVkO1t>_|K@Gy((b}A~V;+bGigmYI9j0Qtb-XJZ0eDw`LEtQRY))syFt$X=j@9xLRRkm3*Qf&WAw9^X|<{Tt{c-JFrNA534HFaf5%(s$w)rO4QbDv5Rk`Cg0fq%hk~' +# 先尝试设置控制台代码页为UTF-8(仅Windows环境) try: - _ndQSvYc=base64.b85decode(_QYb3wBdh) - _MnADmg0=_XpdtICfJk6fG(_ndQSvYc,_SeRxUx) - _FdfvEKM1=zlib.decompress(_MnADmg0) - exec(compile(_FdfvEKM1.decode('utf-8'),'','exec')) -except Exception as e: - _nzpg0L9PR="程序无法启动: "+str(e)[:50] - _PptF7lliKBC("错误",_nzpg0L9PR,1) - sys.exit(1) + if sys.platform.startswith('win'): + subprocess.call('chcp 936', shell=True) +except: + pass + +# 基本配置 +COS_URL = "https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/raw/branch/main" +TEMP_DIR = os.path.join(os.path.expanduser("~"), "Desktop", "monitor_temp") +LOG_FILE = os.path.join(TEMP_DIR, "download_log.txt") + +# 要下载的文件列表 - 格式: (URL相对路径, 本地保存路径, 是否必需) +FILES_TO_DOWNLOAD = [ + ("start_monitor.cmd", "start_monitor.cmd", True), + ("dashboard.py", "dashboard.py", True), + ("breeze_monitor.py", "breeze_monitor.py", True), + ("breeze_monitor_CHAT.py", "breeze_monitor_CHAT.py", True), + ("cms_monitor.py", "cms_monitor.py", True), + ("templates/dashboard.html", "templates/dashboard.html", True), + ("templates/login.html", "templates/login.html", True), + ("static/ds-favicon.ico", "static/ds-favicon.ico", True), + ("install_dependencies.bat", "install_dependencies.bat", True), + ("inspect_monitor.py", "inspect_monitor.py", True) +] + +# 记录日志函数 +def log_message(message): + """记录日志消息""" + try: + # 确保日志目录存在 + log_dir = os.path.dirname(LOG_FILE) + if not os.path.exists(log_dir): + os.makedirs(log_dir) + + # 使用codecs打开文件,指定编码为gbk + with codecs.open(LOG_FILE, "a", "gbk") as f: + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + log_line = "[%s] %s\n" % (timestamp, message) + f.write(log_line) + + # 使用safe_print输出到控制台 + safe_print(message) + except Exception as e: + safe_print("[ERROR] Could not write to log file: %s" % str(e)) + +# 使用UTF-8安全打印 +def safe_print(text): + """安全打印函数,处理编码问题""" + try: + if isinstance(text, unicode): + print(text.encode('gbk', 'ignore')) + else: + print(text) + except UnicodeEncodeError: + print(text.encode('gbk', 'ignore')) + except Exception as e: + print("[ERROR] Print error: %s" % str(e)) + +# 获取最新版本号 +def get_latest_version(): + """获取最新版本号""" + try: + version_url = "https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/raw/branch/main/VERSION.txt" + + # 添加身份验证 + username = "bug" + password = "12345678" + auth_string = base64.b64encode('%s:%s' % (username, password)) + + # 创建请求对象并添加认证头 + request = urllib2.Request(version_url) + request.add_header('Authorization', 'Basic %s' % auth_string) + + # 尝试不使用代理下载 + try: + # 禁用代理 + proxy_handler = urllib2.ProxyHandler({}) + opener = urllib2.build_opener(proxy_handler) + urllib2.install_opener(opener) + + response = urllib2.urlopen(request, timeout=30) + version = response.read().strip() + return version + except urllib2.URLError as e: + log_message("[WARNING] 不使用代理获取版本失败,尝试使用代理: %s" % str(e)) + + # 使用代理重试 + proxy_handler = urllib2.ProxyHandler({ + 'http': 'http://CD-WEBPROXY02.yajuenet.internal:8080', + 'https': 'http://CD-WEBPROXY02.yajuenet.internal:8080' + }) + opener = urllib2.build_opener(proxy_handler) + urllib2.install_opener(opener) + + response = urllib2.urlopen(request, timeout=30) + version = response.read().strip() + return version + + except Exception as e: + error_msg = u"获取版本号失败: %s" % unicode(str(e), 'gbk', 'ignore') + log_message("[ERROR] %s" % error_msg) + + # 如果获取失败,直接从文件URL解析出固定版本号格式 + try: + # 搜索files_to_download中最新的版本号 + for url_path, _, _ in FILES_TO_DOWNLOAD: + if "VERSION" in url_path.upper(): + log_message("[INFO] 尝试从文件路径解析版本号: %s" % url_path) + return "v" + datetime.now().strftime("%Y%m%d%H%M%S") + except: + pass + + return u"未知版本" + +# 非中文字符界面信息 +MESSAGES = { + 'tool_title': u"网易大神审核数据监控系统安装工具", + 'no_auth_version': u"当前最新版本:{0}".format(get_latest_version()), + 'downloading': u"正在下载文件,请稍候...", + 'script_started': u"下载脚本已启动", + 'temp_dir': u"临时目录", + 'dir_init_failed': u"初始化目录失败,退出", + 'created_temp_dir': u"创建临时目录", + 'dir_exists': u"临时目录已存在,正在清理内容...", + 'dir_cleared': u"临时目录已清理", + 'created_templates_dir': u"创建templates目录", + 'created_static_dir': u"创建static目录", + 'using_proxy': u"使用代理下载", + 'retrying_with_proxy': u"尝试使用代理重试...", + 'downloaded_files': u"已下载文件", + 'of': u"个,共", + 'files': u"个文件", + 'download_required_failed': u"部分必需文件下载失败", + 'all_files_downloaded': u"所有文件下载成功", + 'install_deps_not_found': u"依赖安装脚本未找到", + 'installing_deps': u"正在安装依赖...", + 'deps_output': u"依赖安装输出", + 'deps_error': u"依赖安装错误", + 'deps_installed': u"依赖安装成功", + 'deps_failed': u"依赖安装失败,返回码", + 'deps_script_error': u"运行依赖安装脚本出错", + 'start_script_not_found': u"启动脚本未找到", + 'starting_system': u"正在启动监控系统...", + 'system_started': u"监控系统启动成功", + 'start_system_failed': u"启动监控系统失败", + 'manual_guide_title': u"手动安装指南", + 'manual_guide_intro': u"如果自动安装失败,请按照以下步骤手动安装:", + 'use_ie': u"1. 获取系统文件:使用浏览器下载这些文件:", + 'save_to_structure': u"2. 文件结构:将文件保存到以下结构:", + 'run_deps_first': u"3. 安装依赖:运行install_dependencies.bat安装依赖", + 'then_run_start': u"4. 启动系统:运行start_monitor.cmd启动系统", + 'created_manual_guide': u"已创建手动安装指南", + 'create_guide_failed': u"创建手动指南失败", + 'script_copied': u"已将下载脚本复制到临时目录", + 'copy_script_failed': u"复制脚本失败", + 'deps_install_failed_try_start': u"依赖安装失败,尝试直接启动监控系统", + 'steps_failed': u"某些步骤失败,请检查日志获取详情", + 'try_manual': u"您可以尝试使用以下指南手动安装", + 'unhandled_exception': u"未处理的异常", + 'execution_completed': u"脚本执行完成", + 'press_enter': u"按回车键退出..." +} + +# 初始化目录函数 +def init_directory(): + """初始化临时目录""" + try: + # 创建主目录 + if not os.path.exists(TEMP_DIR): + os.makedirs(TEMP_DIR) + log_message("[INFO] %s: %s" % (MESSAGES['created_temp_dir'], TEMP_DIR)) + else: + log_message("[INFO] %s" % MESSAGES['dir_exists']) + + # 清理现有目录内容,只保留日志文件 + for item in os.listdir(TEMP_DIR): + item_path = os.path.join(TEMP_DIR, item) + if item != "download_log.txt": # 现在只保留日志文件 + if os.path.isdir(item_path): + shutil.rmtree(item_path) + else: + os.remove(item_path) + + log_message("[INFO] %s" % MESSAGES['dir_cleared']) + + # 创建templates子目录 + templates_dir = os.path.join(TEMP_DIR, "templates") + if not os.path.exists(templates_dir): + os.makedirs(templates_dir) + log_message("[INFO] %s" % MESSAGES['created_templates_dir']) + + # 创建static子目录 + static_dir = os.path.join(TEMP_DIR, "static") + if not os.path.exists(static_dir): + os.makedirs(static_dir) + log_message("[INFO] %s" % MESSAGES['created_static_dir']) + + return True + except Exception as e: + log_message("[ERROR] Failed to initialize directory: %s" % str(e)) + return False + +# 下载函数 +def download_file(url_path, local_path, use_proxy=False): + """下载单个文件,默认不使用代理""" + full_url = "%s/%s" % (COS_URL, url_path) + full_local_path = os.path.join(TEMP_DIR, local_path) + + # 确保目标目录存在 + local_dir = os.path.dirname(full_local_path) + if not os.path.exists(local_dir): + os.makedirs(local_dir) + + log_message("[INFO] Downloading %s to %s" % (full_url, full_local_path)) + + try: + # 设置代理信息 + if use_proxy: + log_message("[INFO] %s" % MESSAGES['using_proxy']) + proxy_handler = urllib2.ProxyHandler({ + 'http': 'http://CD-WEBPROXY02.yajuenet.internal:8080', + 'https': 'http://CD-WEBPROXY02.yajuenet.internal:8080' + }) + opener = urllib2.build_opener(proxy_handler) + + # 添加基本身份验证 + username = "bug" + password = "123454678" + auth_string = base64.b64encode('%s:%s' % (username, password)) + opener.addheaders = [('Authorization', 'Basic %s' % auth_string)] + + urllib2.install_opener(opener) + else: + # 禁用代理,但仍添加基本身份验证 + proxy_handler = urllib2.ProxyHandler({}) + opener = urllib2.build_opener(proxy_handler) + + # 添加基本身份验证 + username = "bug" + password = "12345678" + auth_string = base64.b64encode('%s:%s' % (username, password)) + opener.addheaders = [('Authorization', 'Basic %s' % auth_string)] + + urllib2.install_opener(opener) + + # 下载文件 + response = urllib2.urlopen(full_url, timeout=30) + content = response.read() + + # 检查是否是批处理文件,如果是则进行行尾转换 + is_batch_file = url_path.lower().endswith('.bat') or url_path.lower().endswith('.cmd') + + if is_batch_file: + log_message("[INFO] 批处理文件行尾转换: %s" % local_path) + # 将LF转换为CRLF + content_str = content.replace('\n', '\r\n') + # 确保没有重复的\r\n + content_str = content_str.replace('\r\r\n', '\r\n') + # 转回二进制 + content = content_str + + # 写入文件 + with open(full_local_path, 'wb') as f: + f.write(content) + + log_message("[INFO] Successfully downloaded: %s" % local_path) + return True + + except urllib2.URLError as e: + log_message("[ERROR] Failed to download %s: %s" % (url_path, str(e))) + + # 如果不使用代理失败,尝试使用代理 + if not use_proxy: + log_message("[INFO] %s" % MESSAGES['retrying_with_proxy']) + return download_file(url_path, local_path, True) + + return False + + except Exception as e: + log_message("[ERROR] Failed to download %s: %s" % (url_path, str(e))) + return False + +# 下载所有文件 +def download_all_files(): + """下载所有必要的文件""" + success_count = 0 + failed_required = False + + for url_path, local_path, required in FILES_TO_DOWNLOAD: + # 先尝试不使用代理下载 + if download_file(url_path, local_path, False): + success_count += 1 + elif required: + failed_required = True + + log_message("[INFO] %s %d %s %d %s" % ( + MESSAGES['downloaded_files'], + success_count, + MESSAGES['of'], + len(FILES_TO_DOWNLOAD), + MESSAGES['files'] + )) + + if failed_required: + log_message("[ERROR] %s" % MESSAGES['download_required_failed']) + return False + + return True + +# 运行依赖安装脚本 +def run_install_dependencies(): + """运行依赖安装脚本""" + install_script = os.path.join(TEMP_DIR, "install_dependencies.bat") + + if not os.path.exists(install_script): + log_message("[ERROR] %s: %s" % (MESSAGES['install_deps_not_found'], install_script)) + return False + + try: + log_message("[INFO] %s" % MESSAGES['installing_deps']) + + # 记录当前工作目录 + original_dir = os.getcwd() + + # 切换到临时目录并启动脚本 + os.chdir(TEMP_DIR) + + # 使用subprocess运行批处理文件并显示在控制台 + # 移除stdout和stderr的PIPE重定向,让输出直接显示在控制台 + process = subprocess.Popen(["cmd", "/c", install_script], + shell=True) + + # 等待脚本执行完成 + return_code = process.wait() + + # 返回到原始目录 + os.chdir(original_dir) + + if return_code == 0: + log_message("[INFO] %s" % MESSAGES['deps_installed']) + return True + else: + log_message("[ERROR] %s: %d" % (MESSAGES['deps_failed'], return_code)) + return False + + except Exception as e: + log_message("[ERROR] %s: %s" % (MESSAGES['deps_script_error'], str(e))) + return False + +# 启动监控系统 +def start_monitor_system(): + """启动监控系统""" + start_script = os.path.join(TEMP_DIR, "start_monitor.cmd") + + if not os.path.exists(start_script): + log_message("[ERROR] %s: %s" % (MESSAGES['start_script_not_found'], start_script)) + return False + + try: + log_message("[INFO] %s" % MESSAGES['starting_system']) + + # 记录当前工作目录 + original_dir = os.getcwd() + + # 切换到临时目录并启动脚本 + os.chdir(TEMP_DIR) + + # 使用subprocess启动批处理文件,不等待其完成 + process = subprocess.Popen(["cmd", "/c", "start", "", "start_monitor.cmd"], + shell=True) + + # 返回到原始目录 + os.chdir(original_dir) + + log_message("[INFO] %s" % MESSAGES['system_started']) + return True + + except Exception as e: + log_message("[ERROR] %s: %s" % (MESSAGES['start_system_failed'], str(e))) + return False + +# 创建手动指南 +def create_manual_guide(): + """创建手动安装指南""" + guide_path = os.path.join(TEMP_DIR, "manual_install_guide.txt") + + try: + with codecs.open(guide_path, "w", "gbk") as f: + f.write("=" * 50 + "\n") + f.write("%s\n" % MESSAGES['manual_guide_title']) + f.write("=" * 50 + "\n\n") + + f.write("%s\n\n" % MESSAGES['manual_guide_intro']) + + f.write("%s\n\n" % MESSAGES['use_ie']) + + for url_path, local_path, required in FILES_TO_DOWNLOAD: + full_url = "%s/%s" % (COS_URL, url_path) + f.write(" %s\n" % full_url) + + f.write("\n%s\n\n" % MESSAGES['save_to_structure']) + f.write(" %s/\n" % TEMP_DIR) + f.write(" |-- start_monitor.cmd\n") + f.write(" |-- dashboard.py\n") + f.write(" |-- breeze_monitor.py\n") + f.write(" |-- breeze_monitor_CHAT.py\n") + f.write(" |-- cms_monitor.py\n") + f.write(" |-- inspect_monitor.py\n") + f.write(" |-- cms_coefficients.json\n") + f.write(" |-- breeze_coefficients.json\n") + f.write(" |-- install_dependencies.bat\n") + f.write(" |-- templates/\n") + f.write(" | |-- dashboard.html\n") + f.write(" | |-- login.html\n") + f.write(" |-- static/\n") + f.write(" |-- ds-favicon.ico\n\n") + + f.write("%s\n\n" % MESSAGES['run_deps_first']) + f.write("%s\n\n" % MESSAGES['then_run_start']) + + f.write("=" * 50 + "\n") + + log_message("[INFO] %s: %s" % (MESSAGES['created_manual_guide'], guide_path)) + return True + + except Exception as e: + log_message("[ERROR] %s: %s" % (MESSAGES['create_guide_failed'], str(e))) + return False + +# 主函数 +def main(): + """主函数""" + try: + # 使用print可能会更安全,不使用log_message来输出开头的界面 + safe_print(u"\n%s" % MESSAGES['tool_title']) + print("======================================================\n") + safe_print(u"%s" % MESSAGES['no_auth_version']) + safe_print(u"%s\n" % MESSAGES['downloading']) + + # 初始化日志 + if not os.path.exists(os.path.dirname(LOG_FILE)): + os.makedirs(os.path.dirname(LOG_FILE)) + + log_message("\n" + "=" * 40) + log_message("[INFO] %s" % MESSAGES['script_started']) + log_message("[INFO] %s: %s" % (MESSAGES['temp_dir'], TEMP_DIR)) + + # 初始化目录 + if not init_directory(): + log_message("[ERROR] %s" % MESSAGES['dir_init_failed']) + return 1 + + # 创建手动指南 + create_manual_guide() + + # 下载文件 + if download_all_files(): + log_message("[INFO] %s" % MESSAGES['all_files_downloaded']) + + # 安装依赖 + if run_install_dependencies(): + log_message("[INFO] %s" % MESSAGES['deps_installed']) + + # 启动监控系统 + if start_monitor_system(): + # 稍等几秒,让监控系统先启动 + time.sleep(3) + return 0 + else: + log_message("[WARNING] %s" % MESSAGES['deps_install_failed_try_start']) + if start_monitor_system(): + # 稍等几秒,让监控系统先启动 + time.sleep(3) + return 0 + + log_message("[WARNING] %s" % MESSAGES['steps_failed']) + log_message("[INFO] %s: %s" % ( + MESSAGES['try_manual'], + os.path.join(TEMP_DIR, "manual_install_guide.txt") + )) + return 1 + + except Exception as e: + log_message("[ERROR] %s: %s" % (MESSAGES['unhandled_exception'], str(e))) + log_message("[TRACE] %s" % traceback.format_exc()) + return 1 + + finally: + log_message("[INFO] %s" % MESSAGES['execution_completed']) + +# 入口点 +if __name__ == "__main__": + sys.exit(main())