CLI Client mode: fetch hosts from URL, write to system, loop with interval
(url: &str, interval_minutes: u32)
| 76 | |
| 77 | /// CLI Client mode: fetch hosts from URL, write to system, loop with interval |
| 78 | async fn run_client_cli(url: &str, interval_minutes: u32) { |
| 79 | println!("🔄 客户端模式启动"); |
| 80 | println!(" 远程地址: {}", url); |
| 81 | println!(" 更新间隔: {} 分钟", interval_minutes); |
| 82 | println!(" 请不要关闭此窗口以保持运行"); |
| 83 | println!(); |
| 84 | |
| 85 | // Initial fetch |
| 86 | cli_log("开始获取 GitHub Hosts..."); |
| 87 | match services::client_fetch_hosts(url).await { |
| 88 | Ok(_) => cli_log("✅ 更新 Github-Hosts 成功!"), |
| 89 | Err(e) => cli_log(&format!("❌ 更新 Github-Hosts 失败: {}", e)), |
| 90 | } |
| 91 | |
| 92 | let interval = std::time::Duration::from_secs(interval_minutes as u64 * 60); |
| 93 | let mut interval_timer = tokio::time::interval(interval); |
| 94 | interval_timer.tick().await; // skip first tick |
| 95 | |
| 96 | // Handle Ctrl+C gracefully |
| 97 | let (shutdown_tx, mut shutdown_rx) = tokio::sync::watch::channel(false); |
| 98 | tokio::spawn(async move { |
| 99 | let _ = tokio::signal::ctrl_c().await; |
| 100 | let _ = shutdown_tx.send(true); |
| 101 | }); |
| 102 | |
| 103 | loop { |
| 104 | tokio::select! { |
| 105 | _ = interval_timer.tick() => { |
| 106 | cli_log("开始获取 GitHub Hosts..."); |
| 107 | match services::client_fetch_hosts(url).await { |
| 108 | Ok(_) => cli_log("✅ 更新 Github-Hosts 成功!"), |
| 109 | Err(e) => cli_log(&format!("❌ 更新 Github-Hosts 失败: {}", e)), |
| 110 | } |
| 111 | } |
| 112 | _ = shutdown_rx.changed() => { |
| 113 | cli_log("🛑 收到停止信号,正在退出..."); |
| 114 | break; |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | // Cleanup sudoers on exit |
| 120 | #[cfg(target_os = "macos")] |
| 121 | hosts::cleanup_privileges(); |
| 122 | } |
| 123 | |
| 124 | /// CLI Server mode: resolve DNS, start HTTP, loop |
| 125 | async fn run_server_cli(port: u16, interval_minutes: u32, template: Option<String>) { |
no test coverage detected