diff --git a/Windows/CS/Framework4.0/Updater/src/main.rs b/Windows/CS/Framework4.0/Updater/src/main.rs index 83e9e5f..c0e1eaf 100644 --- a/Windows/CS/Framework4.0/Updater/src/main.rs +++ b/Windows/CS/Framework4.0/Updater/src/main.rs @@ -2,6 +2,77 @@ use rand::Rng; use std::collections::{HashMap, HashSet}; use std::sync::{Arc, Mutex}; +// ===================== 日志模块 ===================== +/// 日志文件(Mutex 确保线程安全写入) +static LOG_FILE: std::sync::Mutex> = std::sync::Mutex::new(None); + +/// 初始化日志文件(以追加方式打开) +fn init_log_file() { + let mut guard = LOG_FILE.lock().unwrap(); + if guard.is_some() { + return; + } + + let exe_path = match std::env::current_exe() { + Ok(p) => p, + Err(_) => return, + }; + let log_dir = match exe_path.parent() { + Some(d) => d, + None => return, + }; + + let log_name = format!("Updater_{}.log", chrono::Local::now().format("%Y%m%d")); + let log_path = log_dir.join(log_name); + + match std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(&log_path) + { + Ok(file) => { + eprintln!("[日志] 日志文件: {:?}", log_path); + *guard = Some(file); + } + Err(e) => { + eprintln!("[日志] 无法打开日志文件: {}", e); + } + } +} + +/// 日志宏:同时输出到控制台和文件 +macro_rules! log_print { + ($($arg:tt)*) => {{ + let msg = format!($($arg)*); + print!("{}\n", msg); + std::io::stdout().flush().ok(); + if LOG_FILE.lock().unwrap().is_none() { + init_log_file(); + } + if let Some(ref mut file) = *LOG_FILE.lock().unwrap() { + use std::io::Write; + let _ = writeln!(file, "{}", msg); + let _ = file.flush(); + } + }}; +} + +/// 错误日志宏:同时输出到控制台stderr和文件(始终记录) +macro_rules! log_eprintln { + ($($arg:tt)*) => {{ + let msg = format!($($arg)*); + eprintln!("{}", msg); + if LOG_FILE.lock().unwrap().is_none() { + init_log_file(); + } + if let Some(ref mut file) = *LOG_FILE.lock().unwrap() { + use std::io::Write; + let _ = writeln!(file, "{}", msg); + let _ = file.flush(); + } + }}; +} + // ===================== 更新阶段枚举 ===================== /// 更新流程的三个阶段 #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -412,7 +483,7 @@ fn schedule_bootloader_launch( } } Err(e) => { - eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e); + log_eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e); // 启动失败也发送断连信号 if let Some(tx) = shutdown_tx_arc.lock().unwrap().take() { let _ = tx.send(()); @@ -436,7 +507,7 @@ fn schedule_bootloader_launch( } } Err(e) => { - eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e); + log_eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e); if let Some(tx) = shutdown_tx_arc.lock().unwrap().take() { let _ = tx.send(()); } @@ -447,28 +518,24 @@ fn schedule_bootloader_launch( } /// 发送 GetFileMd5 请求 -fn request_file_md5(sender: &cube_lib::websocket::MessageSender, filename: &str, bytes: u64, debug: bool) { +fn request_file_md5(sender: &cube_lib::websocket::MessageSender, filename: &str, bytes: u64) { let msg_str = format!( r#"{{"Type":"GetFileMd5","Data":{{"filename":"{}","bytes":{}}}}}"#, filename, bytes ); - if debug { - let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - println!("{} 发送消息:{}", ts, msg_str); - } + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } /// 发送文件下载请求(断点续传) -fn request_download(sender: &cube_lib::websocket::MessageSender, filename: &str, offset: u64, debug: bool) { +fn request_download(sender: &cube_lib::websocket::MessageSender, filename: &str, offset: u64) { let msg_str = format!( r#"{{"Type":"DownloadFile","Data":{{"filename":"{}","offset":{}}}}}"#, filename, offset ); - if debug { - let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - println!("{} 发送消息:{}", ts, msg_str); - } + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } @@ -666,7 +733,7 @@ fn get_app_tmp_file_size(app_name: &str, relative_path: &str) -> u64 { } /// 获取其他应用的本地版本号(通过 PowerShell 读取 PE 版本) -fn get_local_app_version(app_name: &str, relative_path: &str, _debug: bool) -> String { +fn get_local_app_version(app_name: &str, relative_path: &str) -> String { // 应用主 exe 一般在相对路径的顶级,如 app.exe 或 bin/app.exe // 取第一段目录名或文件名作为 exe 查找起点 let file_path = get_updater_data_dir() @@ -720,16 +787,14 @@ fn request_file_md5_for_app( app_name: &str, relative_path: &str, offset: u64, - debug: bool, ) { let msg_str = format!( r#"{{"Type":"GetFileMd5","Data":{{"filename":"{}","bytes":{}}}}}"#, relative_path, offset ); - if debug { - let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - println!("{} [应用] {} 请求 md5 (offset {}): {}", ts, app_name, offset, relative_path); - } + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} [应用] {} 请求 md5 (offset {}): {}", ts, app_name, offset, relative_path); + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } @@ -738,16 +803,14 @@ fn request_download_for_app( sender: &cube_lib::websocket::MessageSender, relative_path: &str, offset: u64, - debug: bool, ) { let msg_str = format!( r#"{{"Type":"DownloadFile","Data":{{"filename":"{}","offset":{}}}}}"#, relative_path, offset ); - if debug { - let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - println!("{} [应用] 请求下载: {} (offset {})", ts, relative_path, offset); - } + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} [应用] 请求下载: {} (offset {})", ts, relative_path, offset); + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } @@ -1072,16 +1135,14 @@ fn get_app_candidates(debug: bool) -> Vec { /// 递归扫描升级目录,返回 (relative_path, full_path) 列表 /// 跳过 .tmp 文件(如果存在同名非 tmp 文件的话) -fn scan_upgrade_dir(app_name: &str, debug: bool) -> Vec<(String, PathBuf)> { +fn scan_upgrade_dir(app_name: &str) -> Vec<(String, PathBuf)> { let upgrade_base = get_updater_data_dir() .join("Updater") .join("UpGrade") .join(app_name); if !upgrade_base.exists() { - if debug { - println!("[应用] {} 升级目录不存在: {:?}", app_name, upgrade_base); - } + log_print!("[应用] {} 升级目录不存在: {:?}", app_name, upgrade_base); return Vec::new(); } @@ -1107,9 +1168,7 @@ fn scan_upgrade_dir(app_name: &str, debug: bool) -> Vec<(String, PathBuf)> { let non_tmp = rel_str.trim_end_matches(".tmp"); let non_tmp_path = upgrade_base.join(non_tmp); if non_tmp_path.exists() { - if debug { - println!("[应用] 跳过 tmp(同名文件已存在): {} -> {}", rel_str, non_tmp); - } + log_print!("[应用] 跳过 tmp(同名文件已存在): {} -> {}", rel_str, non_tmp); continue; } } @@ -1121,11 +1180,9 @@ fn scan_upgrade_dir(app_name: &str, debug: bool) -> Vec<(String, PathBuf)> { } } - if debug { - println!("[应用] {} 升级文件列表 ({} 个):", app_name, files.len()); - for (rel, _) in &files { - println!("[应用] - {}", rel); - } + log_print!("[应用] {} 升级文件列表 ({} 个):", app_name, files.len()); + for (rel, _) in &files { + log_print!("[应用] - {}", rel); } files @@ -1145,7 +1202,7 @@ fn make_shutdown_channel() -> ( /// 运行 Updater(使用 CubeLib 内置的自动重连) -/// 返回本次运行是否执行了更新(下载了文件) +/// 返回本次运行是否更新了 Updater 自身(只有 Updater 更新了才需要退出重启) async fn run_updater(debug_mode: bool) -> bool { // 创建本次运行的上下文 let ctx = Arc::new(UpdateContext::default()); @@ -1223,16 +1280,15 @@ async fn run_updater(debug_mode: bool) -> bool { let update_check_done_clone2 = update_check_done_clone.clone(); client.on_message(move |msg_type, data, sender| { let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - if debug_msg { - // 收到消息日志:data 是完整 parsed 对象,取其中的 Data 字段打印 - let actual_data = data.get("Data").unwrap_or(&serde_json::Value::Null); - let data_str = serde_json::to_string(actual_data).unwrap_or_else(|_| "{}".to_string()); - println!("{} 收到消息:{{\"Type\":{},\"Data\":{}}}", - ts, - serde_json::to_string(&msg_type).unwrap_or_default(), - data_str - ); - } + + // 收到消息日志(始终记录) + let actual_data = data.get("Data").unwrap_or(&serde_json::Value::Null); + let data_str = serde_json::to_string(actual_data).unwrap_or_else(|_| "{}".to_string()); + log_print!("{} 收到消息:{{\"Type\":{},\"Data\":{}}}", + ts, + serde_json::to_string(&msg_type).unwrap_or_default(), + data_str + ); // 收到 welcome 后,根据当前阶段发送 GetFileVer if msg_type == "welcome" { @@ -1243,14 +1299,12 @@ async fn run_updater(debug_mode: bool) -> bool { match current_phase { UpdatePhase::BootLoader => { // 阶段1:只请求 BootLoader.exe - println!("{} [阶段1] 检查 BootLoader...", ts); + log_print!("{} [阶段1] 检查 BootLoader...", ts); let msg_str = format!( r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["BootLoader.exe"]}}}}"#, device_number ); - if debug_msg { - println!("{} 发送消息:{}", ts, msg_str); - } + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } _ => { @@ -1274,40 +1328,42 @@ async fn run_updater(debug_mode: bool) -> bool { let local_version = get_local_file_version("BootLoader.exe"); let tmp_size = get_tmp_file_size("BootLoader.exe"); - println!("{} [版本] BootLoader.exe: 服务端={}, 本地={}", ts, server_version, local_version); + log_print!("{} [版本] BootLoader.exe: 服务端={}, 本地={}", ts, server_version, local_version); let need_update = local_version == "0.0.0" || version_less_than(&local_version, server_version); if need_update { if tmp_size > 0 { - println!("{} [续传] BootLoader.exe 发现未完成下载,请求 hash 校验...", ts); - request_file_md5(&sender, "BootLoader.exe", tmp_size, debug_msg); + log_print!("{} [续传] BootLoader.exe 发现未完成下载,请求 hash 校验...", ts); + request_file_md5(&sender, "BootLoader.exe", tmp_size); } else { - println!("{} [升级] BootLoader.exe 需要更新,开始下载...", ts); - request_download(&sender, "BootLoader.exe", 0, debug_msg); + log_print!("{} [升级] BootLoader.exe 需要更新,开始下载...", ts); + request_download(&sender, "BootLoader.exe", 0); } update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst); } else { - println!("{} [版本] BootLoader.exe 版本已是最新", ts); + log_print!("{} [版本] BootLoader.exe 版本已是最新", ts); // 推进到阶段2 let next_phase = UpdatePhase::Updater; *ctx_clone.current_phase.lock().unwrap() = next_phase; - println!("{} [阶段2] 检查 Updater...", ts); + log_print!("{} [阶段2] 检查 Updater...", ts); let msg_str = format!( r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#, device_number ); + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } } else { // BootLoader 不在响应中,推进到阶段2 *ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Updater; - println!("{} [阶段2] 检查 Updater...", ts); + log_print!("{} [阶段2] 检查 Updater...", ts); let msg_str = format!( r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#, device_number ); + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } } @@ -1322,25 +1378,25 @@ async fn run_updater(debug_mode: bool) -> bool { // 保存 Updater.exe 的服务端版本号 *ctx_clone.server_updater_version.lock().unwrap() = Some(server_version.to_string()); - println!("{} [版本] Updater.exe: 服务端={}, 本地={}", ts, server_version, local_version); + log_print!("{} [版本] Updater.exe: 服务端={}, 本地={}", ts, server_version, local_version); let need_update = local_version == "0.0.0" || version_less_than(&local_version, server_version); if need_update { if tmp_size > 0 { - println!("{} [续传] Updater.exe 发现未完成下载,请求 hash 校验...", ts); - request_file_md5(&sender, "Updater.exe", tmp_size, debug_msg); + log_print!("{} [续传] Updater.exe 发现未完成下载,请求 hash 校验...", ts); + request_file_md5(&sender, "Updater.exe", tmp_size); } else { - println!("{} [升级] Updater.exe 需要更新,开始下载...", ts); - request_download(&sender, "Updater.exe", 0, debug_msg); + log_print!("{} [升级] Updater.exe 需要更新,开始下载...", ts); + request_download(&sender, "Updater.exe", 0); } update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst); } else { - println!("{} [版本] Updater.exe 版本已是最新", ts); + log_print!("{} [版本] Updater.exe 版本已是最新", ts); // 检查是否有旧的 Updater.new.exe if has_updater_new_exe() { let updater_new_path = get_updater_data_dir().join("Updater.new.exe"); let _ = fs::remove_file(&updater_new_path); - println!("{} [清理] 删除旧的 Updater.new.exe", ts); + log_print!("{} [清理] 删除旧的 Updater.new.exe", ts); } // 推进到阶段3 @@ -1348,7 +1404,7 @@ async fn run_updater(debug_mode: bool) -> bool { if candidates.is_empty() { // 没有候选应用,所有阶段完成 *ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Complete; - println!("{} [阶段3] 没有候选应用,所有阶段完成", ts); + log_print!("{} [阶段3] 没有候选应用,所有阶段完成", ts); update_check_done_clone2.store(true, std::sync::atomic::Ordering::SeqCst); // 发送断连信号 if let Some(tx) = shutdown_tx_arc_clone.lock().unwrap().take() { @@ -1356,7 +1412,7 @@ async fn run_updater(debug_mode: bool) -> bool { } } else { *ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Apps; - println!("{} [阶段3] 检查应用: {:?}", ts, candidates); + log_print!("{} [阶段3] 检查应用: {:?}", ts, candidates); // 构建应用版本查询 let mut file_list = Vec::new(); @@ -1368,6 +1424,7 @@ async fn run_updater(debug_mode: bool) -> bool { r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":{}}}}}"#, device_number, file_list_json ); + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } } @@ -1394,6 +1451,7 @@ async fn run_updater(debug_mode: bool) -> bool { r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":{}}}}}"#, device_number, file_list_json ); + log_print!("{} 发送消息:{}", ts, msg_str); sender.send(msg_str); } } @@ -1408,9 +1466,9 @@ async fn run_updater(debug_mode: bool) -> bool { let exe_name = format!("{}.exe", app_name); if let Some(server_ver) = file_versions.get(&exe_name) { let server_version = server_ver.as_str().unwrap_or("0.0.0"); - let local_version = get_local_app_version(app_name, &exe_name, debug_msg); + let local_version = get_local_app_version(app_name, &exe_name); - println!("{} [应用] {}: 服务端={}, 本地={}", ts, app_name, server_version, local_version); + log_print!("{} [应用] {}: 服务端={}, 本地={}", ts, app_name, server_version, local_version); if local_version == "0.0.0" || version_less_than(&local_version, server_version) { apps_to_update.push(app_name.clone()); @@ -1421,18 +1479,18 @@ async fn run_updater(debug_mode: bool) -> bool { // 处理需要更新的应用 let mut has_downloads = false; for app_name in &apps_to_update { - let upgrade_files = scan_upgrade_dir(app_name, debug_msg); + let upgrade_files = scan_upgrade_dir(app_name); if upgrade_files.is_empty() { - println!("{} [应用] {} 没有升级文件,跳过", ts, app_name); + log_print!("{} [应用] {} 没有升级文件,跳过", ts, app_name); continue; } for (rel_path, _) in upgrade_files { let tmp_size = get_app_tmp_file_size(app_name, &rel_path); if tmp_size > 0 { - request_file_md5_for_app(&sender, app_name, &rel_path, tmp_size, debug_msg); + request_file_md5_for_app(&sender, app_name, &rel_path, tmp_size); } else { - request_download_for_app(&sender, &rel_path, 0, debug_msg); + request_download_for_app(&sender, &rel_path, 0); } update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst); has_downloads = true; @@ -1491,15 +1549,14 @@ async fn run_updater(debug_mode: bool) -> bool { let tmp_filename = format!("{}.tmp", filename); let local_md5 = compute_file_hash_in_dir(app_name, &tmp_filename, bytes, debug_msg); - if debug_msg { - let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - if let Some(ref lm) = local_md5 { - println!("{} [应用] {} md5: 本地={}, 服务端={}", ts, filename, lm, server_md5); - } + + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + if let Some(ref lm) = local_md5 { + log_print!("{} [应用] {} md5: 本地={}, 服务端={}", ts, filename, lm, server_md5); } if local_md5.as_deref() == Some(server_md5) { - request_download_for_app(&sender, filename, bytes, debug_msg); + request_download_for_app(&sender, filename, bytes); } else { let tmp_path = get_updater_data_dir() .join("Updater") @@ -1507,7 +1564,7 @@ async fn run_updater(debug_mode: bool) -> bool { .join(app_name) .join(&tmp_filename); let _ = fs::remove_file(&tmp_path); - request_download_for_app(&sender, filename, 0, debug_msg); + request_download_for_app(&sender, filename, 0); } break; } @@ -1539,20 +1596,16 @@ async fn run_updater(debug_mode: bool) -> bool { // 比较 md5 if local_md5.as_deref() == Some(server_md5) { // md5 相同,从 offset bytes 处续传 - if debug_msg { - let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - println!("{} [续传] {} md5匹配,从 {} 字节处续传", ts, filename, bytes); - } - request_download(&sender, filename, bytes, debug_msg); + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} [续传] {} md5匹配,从 {} 字节处续传", ts, filename, bytes); + request_download(&sender, filename, bytes); } else { // md5 不同,删除临时文件,重新下载 - if debug_msg { - let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - println!("{} [续传] {} md5不匹配,重新下载", ts, filename); - } + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} [续传] {} md5不匹配,重新下载", ts, filename); let tmp_path = get_updater_data_dir().join(&tmp_filename); let _ = fs::remove_file(&tmp_path); - request_download(&sender, filename, 0, debug_msg); + request_download(&sender, filename, 0); } } } @@ -1639,26 +1692,31 @@ async fn run_updater(debug_mode: bool) -> bool { // ========== BootLoader/Updater 的 DownloadComplete 处理 ========== let completed = handle_download_complete(&ctx_clone, data_obj, debug_msg); if let Some(ref completed_file) = completed { - // BootLoader.exe 下载完成 + // BootLoader.exe 下载完成,推进到阶段2检查 Updater 版本 if completed_file == "BootLoader.exe" { if !bootloader_downloaded_clone2.load(std::sync::atomic::Ordering::SeqCst) { bootloader_downloaded_clone2.store(true, std::sync::atomic::Ordering::SeqCst); if debug_msg { let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - println!("{} [升级] BootLoader.exe 下载完成,开始下载 Updater.exe...", ts); + log_print!("{} [升级] BootLoader.exe 下载完成,推进到阶段2检查 Updater...", ts); } - // 开始下载 Updater.exe - request_download(&sender, "Updater.exe", 0, debug_msg); + // 推进到阶段2,由阶段2决定是否需要下载 Updater + *ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Updater; + let msg = format!( + r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#, + device_number + ); + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} 发送消息:{}", ts, msg); + sender.send(msg); } } // Updater.new.exe 下载完成 else if completed_file == "Updater.new.exe" { if !updater_downloaded_clone2.load(std::sync::atomic::Ordering::SeqCst) { updater_downloaded_clone2.store(true, std::sync::atomic::Ordering::SeqCst); - if debug_msg { - let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); - println!("{} [升级] Updater.new.exe 下载完成(DownloadComplete),准备启动 BootLoader...", ts); - } + let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); + log_print!("{} [升级] Updater.new.exe 下载完成(DownloadComplete),准备启动 BootLoader...", ts); schedule_bootloader_launch(debug_msg, shutdown_tx_arc.clone()); } } @@ -1679,7 +1737,7 @@ async fn run_updater(debug_mode: bool) -> bool { // 设置错误回调 client.on_error(|error| { - eprintln!("[错误] WebSocket: {}", error); + log_eprintln!("[错误] WebSocket: {}", error); }); // 设置首次连接回调 @@ -1763,8 +1821,8 @@ async fn run_updater(debug_mode: bool) -> bool { println!("Updater 本次运行结束"); } - // 返回是否执行了更新(下载了文件) - update_performed.load(std::sync::atomic::Ordering::SeqCst) + // 返回 Updater 是否被更新(只有 Updater 更新了才需要退出重启) + updater_downloaded.load(std::sync::atomic::Ordering::SeqCst) } #[tokio::main] @@ -1799,11 +1857,11 @@ async fn main() { // 主循环:常驻运行,定期检查更新 loop { // 运行一次 Updater(连接、检查、下载) - let update_performed = run_updater(config.debug_mode).await; + let updater_updated = run_updater(config.debug_mode).await; - if update_performed { + if updater_updated { if config.debug_mode { - println!("Updater 执行了更新,即将退出(等待 BootLoader 重启)"); + println!("Updater 自身已更新,即将退出(等待 BootLoader 重启)"); } std::process::exit(0); }