修改日志

This commit is contained in:
zqm
2026-04-09 15:15:37 +08:00
parent 64a42bebbc
commit 5be97844a3

View File

@@ -2,6 +2,77 @@ use rand::Rng;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
// ===================== 日志模块 =====================
/// 日志文件Mutex 确保线程安全写入)
static LOG_FILE: std::sync::Mutex<Option<std::fs::File>> = 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -412,7 +483,7 @@ fn schedule_bootloader_launch(
} }
} }
Err(e) => { Err(e) => {
eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e); log_eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e);
// 启动失败也发送断连信号 // 启动失败也发送断连信号
if let Some(tx) = shutdown_tx_arc.lock().unwrap().take() { if let Some(tx) = shutdown_tx_arc.lock().unwrap().take() {
let _ = tx.send(()); let _ = tx.send(());
@@ -436,7 +507,7 @@ fn schedule_bootloader_launch(
} }
} }
Err(e) => { Err(e) => {
eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e); log_eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e);
if let Some(tx) = shutdown_tx_arc.lock().unwrap().take() { if let Some(tx) = shutdown_tx_arc.lock().unwrap().take() {
let _ = tx.send(()); let _ = tx.send(());
} }
@@ -447,28 +518,24 @@ fn schedule_bootloader_launch(
} }
/// 发送 GetFileMd5 请求 /// 发送 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!( let msg_str = format!(
r#"{{"Type":"GetFileMd5","Data":{{"filename":"{}","bytes":{}}}}}"#, r#"{{"Type":"GetFileMd5","Data":{{"filename":"{}","bytes":{}}}}}"#,
filename, bytes filename, bytes
); );
if debug { let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); log_print!("{} 发送消息:{}", ts, msg_str);
println!("{} 发送消息:{}", ts, msg_str);
}
sender.send(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!( let msg_str = format!(
r#"{{"Type":"DownloadFile","Data":{{"filename":"{}","offset":{}}}}}"#, r#"{{"Type":"DownloadFile","Data":{{"filename":"{}","offset":{}}}}}"#,
filename, offset filename, offset
); );
if debug { let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); log_print!("{} 发送消息:{}", ts, msg_str);
println!("{} 发送消息:{}", ts, msg_str);
}
sender.send(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 版本) /// 获取其他应用的本地版本号(通过 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 一般在相对路径的顶级,如 app.exe 或 bin/app.exe
// 取第一段目录名或文件名作为 exe 查找起点 // 取第一段目录名或文件名作为 exe 查找起点
let file_path = get_updater_data_dir() let file_path = get_updater_data_dir()
@@ -720,16 +787,14 @@ fn request_file_md5_for_app(
app_name: &str, app_name: &str,
relative_path: &str, relative_path: &str,
offset: u64, offset: u64,
debug: bool,
) { ) {
let msg_str = format!( let msg_str = format!(
r#"{{"Type":"GetFileMd5","Data":{{"filename":"{}","bytes":{}}}}}"#, r#"{{"Type":"GetFileMd5","Data":{{"filename":"{}","bytes":{}}}}}"#,
relative_path, offset relative_path, offset
); );
if debug { let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); log_print!("{} [应用] {} 请求 md5 (offset {}): {}", ts, app_name, offset, relative_path);
println!("{} [应用] {} 请求 md5 (offset {}): {}", ts, app_name, offset, relative_path); log_print!("{} 发送消息:{}", ts, msg_str);
}
sender.send(msg_str); sender.send(msg_str);
} }
@@ -738,16 +803,14 @@ fn request_download_for_app(
sender: &cube_lib::websocket::MessageSender, sender: &cube_lib::websocket::MessageSender,
relative_path: &str, relative_path: &str,
offset: u64, offset: u64,
debug: bool,
) { ) {
let msg_str = format!( let msg_str = format!(
r#"{{"Type":"DownloadFile","Data":{{"filename":"{}","offset":{}}}}}"#, r#"{{"Type":"DownloadFile","Data":{{"filename":"{}","offset":{}}}}}"#,
relative_path, offset relative_path, offset
); );
if debug { let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); log_print!("{} [应用] 请求下载: {} (offset {})", ts, relative_path, offset);
println!("{} [应用] 请求下载: {} (offset {})", ts, relative_path, offset); log_print!("{} 发送消息:{}", ts, msg_str);
}
sender.send(msg_str); sender.send(msg_str);
} }
@@ -1072,16 +1135,14 @@ fn get_app_candidates(debug: bool) -> Vec<String> {
/// 递归扫描升级目录,返回 (relative_path, full_path) 列表 /// 递归扫描升级目录,返回 (relative_path, full_path) 列表
/// 跳过 .tmp 文件(如果存在同名非 tmp 文件的话) /// 跳过 .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() let upgrade_base = get_updater_data_dir()
.join("Updater") .join("Updater")
.join("UpGrade") .join("UpGrade")
.join(app_name); .join(app_name);
if !upgrade_base.exists() { if !upgrade_base.exists() {
if debug { log_print!("[应用] {} 升级目录不存在: {:?}", app_name, upgrade_base);
println!("[应用] {} 升级目录不存在: {:?}", app_name, upgrade_base);
}
return Vec::new(); 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 = rel_str.trim_end_matches(".tmp");
let non_tmp_path = upgrade_base.join(non_tmp); let non_tmp_path = upgrade_base.join(non_tmp);
if non_tmp_path.exists() { if non_tmp_path.exists() {
if debug { log_print!("[应用] 跳过 tmp同名文件已存在: {} -> {}", rel_str, non_tmp);
println!("[应用] 跳过 tmp同名文件已存在: {} -> {}", rel_str, non_tmp);
}
continue; continue;
} }
} }
@@ -1121,11 +1180,9 @@ fn scan_upgrade_dir(app_name: &str, debug: bool) -> Vec<(String, PathBuf)> {
} }
} }
if debug { log_print!("[应用] {} 升级文件列表 ({} 个):", app_name, files.len());
println!("[应用] {} 升级文件列表 ({} 个):", app_name, files.len()); for (rel, _) in &files {
for (rel, _) in &files { log_print!("[应用] - {}", rel);
println!("[应用] - {}", rel);
}
} }
files files
@@ -1145,7 +1202,7 @@ fn make_shutdown_channel() -> (
/// 运行 Updater使用 CubeLib 内置的自动重连) /// 运行 Updater使用 CubeLib 内置的自动重连)
/// 返回本次运行是否执行了更新(下载了文件 /// 返回本次运行是否更新了 Updater 自身(只有 Updater 更新了才需要退出重启
async fn run_updater(debug_mode: bool) -> bool { async fn run_updater(debug_mode: bool) -> bool {
// 创建本次运行的上下文 // 创建本次运行的上下文
let ctx = Arc::new(UpdateContext::default()); 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(); let update_check_done_clone2 = update_check_done_clone.clone();
client.on_message(move |msg_type, data, sender| { client.on_message(move |msg_type, data, sender| {
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); 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 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()); let data_str = serde_json::to_string(actual_data).unwrap_or_else(|_| "{}".to_string());
println!("{} 收到消息:{{\"Type\":{},\"Data\":{}}}", log_print!("{} 收到消息:{{\"Type\":{},\"Data\":{}}}",
ts, ts,
serde_json::to_string(&msg_type).unwrap_or_default(), serde_json::to_string(&msg_type).unwrap_or_default(),
data_str data_str
); );
}
// 收到 welcome 后,根据当前阶段发送 GetFileVer // 收到 welcome 后,根据当前阶段发送 GetFileVer
if msg_type == "welcome" { if msg_type == "welcome" {
@@ -1243,14 +1299,12 @@ async fn run_updater(debug_mode: bool) -> bool {
match current_phase { match current_phase {
UpdatePhase::BootLoader => { UpdatePhase::BootLoader => {
// 阶段1只请求 BootLoader.exe // 阶段1只请求 BootLoader.exe
println!("{} [阶段1] 检查 BootLoader...", ts); log_print!("{} [阶段1] 检查 BootLoader...", ts);
let msg_str = format!( let msg_str = format!(
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["BootLoader.exe"]}}}}"#, r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["BootLoader.exe"]}}}}"#,
device_number device_number
); );
if debug_msg { log_print!("{} 发送消息:{}", ts, msg_str);
println!("{} 发送消息:{}", ts, msg_str);
}
sender.send(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 local_version = get_local_file_version("BootLoader.exe");
let tmp_size = get_tmp_file_size("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); let need_update = local_version == "0.0.0" || version_less_than(&local_version, server_version);
if need_update { if need_update {
if tmp_size > 0 { if tmp_size > 0 {
println!("{} [续传] BootLoader.exe 发现未完成下载,请求 hash 校验...", ts); log_print!("{} [续传] BootLoader.exe 发现未完成下载,请求 hash 校验...", ts);
request_file_md5(&sender, "BootLoader.exe", tmp_size, debug_msg); request_file_md5(&sender, "BootLoader.exe", tmp_size);
} else { } else {
println!("{} [升级] BootLoader.exe 需要更新,开始下载...", ts); log_print!("{} [升级] BootLoader.exe 需要更新,开始下载...", ts);
request_download(&sender, "BootLoader.exe", 0, debug_msg); request_download(&sender, "BootLoader.exe", 0);
} }
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst); update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
} else { } else {
println!("{} [版本] BootLoader.exe 版本已是最新", ts); log_print!("{} [版本] BootLoader.exe 版本已是最新", ts);
// 推进到阶段2 // 推进到阶段2
let next_phase = UpdatePhase::Updater; let next_phase = UpdatePhase::Updater;
*ctx_clone.current_phase.lock().unwrap() = next_phase; *ctx_clone.current_phase.lock().unwrap() = next_phase;
println!("{} [阶段2] 检查 Updater...", ts); log_print!("{} [阶段2] 检查 Updater...", ts);
let msg_str = format!( let msg_str = format!(
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#, r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#,
device_number device_number
); );
log_print!("{} 发送消息:{}", ts, msg_str);
sender.send(msg_str); sender.send(msg_str);
} }
} else { } else {
// BootLoader 不在响应中推进到阶段2 // BootLoader 不在响应中推进到阶段2
*ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Updater; *ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Updater;
println!("{} [阶段2] 检查 Updater...", ts); log_print!("{} [阶段2] 检查 Updater...", ts);
let msg_str = format!( let msg_str = format!(
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#, r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#,
device_number device_number
); );
log_print!("{} 发送消息:{}", ts, msg_str);
sender.send(msg_str); sender.send(msg_str);
} }
} }
@@ -1322,25 +1378,25 @@ async fn run_updater(debug_mode: bool) -> bool {
// 保存 Updater.exe 的服务端版本号 // 保存 Updater.exe 的服务端版本号
*ctx_clone.server_updater_version.lock().unwrap() = Some(server_version.to_string()); *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); let need_update = local_version == "0.0.0" || version_less_than(&local_version, server_version);
if need_update { if need_update {
if tmp_size > 0 { if tmp_size > 0 {
println!("{} [续传] Updater.exe 发现未完成下载,请求 hash 校验...", ts); log_print!("{} [续传] Updater.exe 发现未完成下载,请求 hash 校验...", ts);
request_file_md5(&sender, "Updater.exe", tmp_size, debug_msg); request_file_md5(&sender, "Updater.exe", tmp_size);
} else { } else {
println!("{} [升级] Updater.exe 需要更新,开始下载...", ts); log_print!("{} [升级] Updater.exe 需要更新,开始下载...", ts);
request_download(&sender, "Updater.exe", 0, debug_msg); request_download(&sender, "Updater.exe", 0);
} }
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst); update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
} else { } else {
println!("{} [版本] Updater.exe 版本已是最新", ts); log_print!("{} [版本] Updater.exe 版本已是最新", ts);
// 检查是否有旧的 Updater.new.exe // 检查是否有旧的 Updater.new.exe
if has_updater_new_exe() { if has_updater_new_exe() {
let updater_new_path = get_updater_data_dir().join("Updater.new.exe"); let updater_new_path = get_updater_data_dir().join("Updater.new.exe");
let _ = fs::remove_file(&updater_new_path); let _ = fs::remove_file(&updater_new_path);
println!("{} [清理] 删除旧的 Updater.new.exe", ts); log_print!("{} [清理] 删除旧的 Updater.new.exe", ts);
} }
// 推进到阶段3 // 推进到阶段3
@@ -1348,7 +1404,7 @@ async fn run_updater(debug_mode: bool) -> bool {
if candidates.is_empty() { if candidates.is_empty() {
// 没有候选应用,所有阶段完成 // 没有候选应用,所有阶段完成
*ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Complete; *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); update_check_done_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
// 发送断连信号 // 发送断连信号
if let Some(tx) = shutdown_tx_arc_clone.lock().unwrap().take() { if let Some(tx) = shutdown_tx_arc_clone.lock().unwrap().take() {
@@ -1356,7 +1412,7 @@ async fn run_updater(debug_mode: bool) -> bool {
} }
} else { } else {
*ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Apps; *ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Apps;
println!("{} [阶段3] 检查应用: {:?}", ts, candidates); log_print!("{} [阶段3] 检查应用: {:?}", ts, candidates);
// 构建应用版本查询 // 构建应用版本查询
let mut file_list = Vec::new(); 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":{}}}}}"#, r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":{}}}}}"#,
device_number, file_list_json device_number, file_list_json
); );
log_print!("{} 发送消息:{}", ts, msg_str);
sender.send(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":{}}}}}"#, r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":{}}}}}"#,
device_number, file_list_json device_number, file_list_json
); );
log_print!("{} 发送消息:{}", ts, msg_str);
sender.send(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); let exe_name = format!("{}.exe", app_name);
if let Some(server_ver) = file_versions.get(&exe_name) { if let Some(server_ver) = file_versions.get(&exe_name) {
let server_version = server_ver.as_str().unwrap_or("0.0.0"); 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) { if local_version == "0.0.0" || version_less_than(&local_version, server_version) {
apps_to_update.push(app_name.clone()); apps_to_update.push(app_name.clone());
@@ -1421,18 +1479,18 @@ async fn run_updater(debug_mode: bool) -> bool {
// 处理需要更新的应用 // 处理需要更新的应用
let mut has_downloads = false; let mut has_downloads = false;
for app_name in &apps_to_update { 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() { if upgrade_files.is_empty() {
println!("{} [应用] {} 没有升级文件,跳过", ts, app_name); log_print!("{} [应用] {} 没有升级文件,跳过", ts, app_name);
continue; continue;
} }
for (rel_path, _) in upgrade_files { for (rel_path, _) in upgrade_files {
let tmp_size = get_app_tmp_file_size(app_name, &rel_path); let tmp_size = get_app_tmp_file_size(app_name, &rel_path);
if tmp_size > 0 { 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 { } 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); update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
has_downloads = true; has_downloads = true;
@@ -1491,15 +1549,14 @@ async fn run_updater(debug_mode: bool) -> bool {
let tmp_filename = format!("{}.tmp", filename); let tmp_filename = format!("{}.tmp", filename);
let local_md5 = compute_file_hash_in_dir(app_name, &tmp_filename, bytes, debug_msg); 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"); let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
if let Some(ref lm) = local_md5 { if let Some(ref lm) = local_md5 {
println!("{} [应用] {} md5: 本地={}, 服务端={}", ts, filename, lm, server_md5); log_print!("{} [应用] {} md5: 本地={}, 服务端={}", ts, filename, lm, server_md5);
}
} }
if local_md5.as_deref() == Some(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 { } else {
let tmp_path = get_updater_data_dir() let tmp_path = get_updater_data_dir()
.join("Updater") .join("Updater")
@@ -1507,7 +1564,7 @@ async fn run_updater(debug_mode: bool) -> bool {
.join(app_name) .join(app_name)
.join(&tmp_filename); .join(&tmp_filename);
let _ = fs::remove_file(&tmp_path); let _ = fs::remove_file(&tmp_path);
request_download_for_app(&sender, filename, 0, debug_msg); request_download_for_app(&sender, filename, 0);
} }
break; break;
} }
@@ -1539,20 +1596,16 @@ async fn run_updater(debug_mode: bool) -> bool {
// 比较 md5 // 比较 md5
if local_md5.as_deref() == Some(server_md5) { if local_md5.as_deref() == Some(server_md5) {
// md5 相同,从 offset bytes 处续传 // md5 相同,从 offset bytes 处续传
if debug_msg { let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); log_print!("{} [续传] {} md5匹配从 {} 字节处续传", ts, filename, bytes);
println!("{} [续传] {} md5匹配{} 字节处续传", ts, filename, bytes); request_download(&sender, filename, bytes);
}
request_download(&sender, filename, bytes, debug_msg);
} else { } else {
// md5 不同,删除临时文件,重新下载 // md5 不同,删除临时文件,重新下载
if debug_msg { let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); log_print!("{} [续传] {} md5不匹配重新下载", ts, filename);
println!("{} [续传] {} md5不匹配重新下载", ts, filename);
}
let tmp_path = get_updater_data_dir().join(&tmp_filename); let tmp_path = get_updater_data_dir().join(&tmp_filename);
let _ = fs::remove_file(&tmp_path); 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 处理 ========== // ========== BootLoader/Updater 的 DownloadComplete 处理 ==========
let completed = handle_download_complete(&ctx_clone, data_obj, debug_msg); let completed = handle_download_complete(&ctx_clone, data_obj, debug_msg);
if let Some(ref completed_file) = completed { if let Some(ref completed_file) = completed {
// BootLoader.exe 下载完成 // BootLoader.exe 下载完成推进到阶段2检查 Updater 版本
if completed_file == "BootLoader.exe" { if completed_file == "BootLoader.exe" {
if !bootloader_downloaded_clone2.load(std::sync::atomic::Ordering::SeqCst) { if !bootloader_downloaded_clone2.load(std::sync::atomic::Ordering::SeqCst) {
bootloader_downloaded_clone2.store(true, std::sync::atomic::Ordering::SeqCst); bootloader_downloaded_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
if debug_msg { if debug_msg {
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); 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 // 推进到阶段2由阶段2决定是否需要下载 Updater
request_download(&sender, "Updater.exe", 0, debug_msg); *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 下载完成 // Updater.new.exe 下载完成
else if completed_file == "Updater.new.exe" { else if completed_file == "Updater.new.exe" {
if !updater_downloaded_clone2.load(std::sync::atomic::Ordering::SeqCst) { if !updater_downloaded_clone2.load(std::sync::atomic::Ordering::SeqCst) {
updater_downloaded_clone2.store(true, 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");
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"); log_print!("{} [升级] Updater.new.exe 下载完成DownloadComplete准备启动 BootLoader...", ts);
println!("{} [升级] Updater.new.exe 下载完成DownloadComplete准备启动 BootLoader...", ts);
}
schedule_bootloader_launch(debug_msg, shutdown_tx_arc.clone()); 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| { 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 本次运行结束"); println!("Updater 本次运行结束");
} }
// 返回是否执行了更新(下载了文件 // 返回 Updater 是否被更新(只有 Updater 更新了才需要退出重启
update_performed.load(std::sync::atomic::Ordering::SeqCst) updater_downloaded.load(std::sync::atomic::Ordering::SeqCst)
} }
#[tokio::main] #[tokio::main]
@@ -1799,11 +1857,11 @@ async fn main() {
// 主循环:常驻运行,定期检查更新 // 主循环:常驻运行,定期检查更新
loop { loop {
// 运行一次 Updater连接、检查、下载 // 运行一次 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 { if config.debug_mode {
println!("Updater 执行了更新,即将退出(等待 BootLoader 重启)"); println!("Updater 自身已更新,即将退出(等待 BootLoader 重启)");
} }
std::process::exit(0); std::process::exit(0);
} }