fix: 消除 Win 闪终端 + 替换慢 CLI 操作为直接进程管理

闪终端修复:
- extensions.rs: 提取 cftunnel_cmd() 助手,Windows 自动加
  CREATE_NO_WINDOW;get_cftunnel_status/action/logs 全部改用

CLI 替换:
- config.rs reload_gateway / restart_gateway: Windows/Linux 改调
  service::restart_service(),删除慢 openclaw gateway restart CLI 调用
- config.rs uninstall_gateway: Windows 改用直接 taskkill,
  Linux 改用 pkill,不再调用 openclaw gateway stop CLI
This commit is contained in:
晴天
2026-03-04 14:56:49 +08:00
parent 73d7d6e7f5
commit 7f2f6db842
2 changed files with 36 additions and 25 deletions

View File

@@ -625,7 +625,7 @@ fn get_uid() -> Result<u32, String> {
/// 重载 Gateway 服务
/// macOS: launchctl kickstart -k
/// Windows/Linux: openclaw gateway restart
/// Windows/Linux: 直接通过进程管理重启(不走慢 CLI
#[tauri::command]
pub async fn reload_gateway() -> Result<String, String> {
#[cfg(target_os = "macos")]
@@ -646,23 +646,10 @@ pub async fn reload_gateway() -> Result<String, String> {
}
#[cfg(not(target_os = "macos"))]
{
use crate::utils::openclaw_command_async;
let cli_check = openclaw_command_async().arg("--version").output().await;
match cli_check {
Ok(o) if o.status.success() => {}
_ => return Err("openclaw CLI 未安装,无法重载 Gateway".into()),
}
let output = openclaw_command_async()
.args(["gateway", "restart"])
.output()
// 直接调用服务管理(进程级别),避免慢 CLI 调用
crate::commands::service::restart_service("ai.openclaw.gateway".into())
.await
.map_err(|e| format!("重载失败: {e}"))?;
if output.status.success() {
Ok("Gateway 已重载".to_string())
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
Err(format!("重载失败: {stderr}"))
}
.map(|_| "Gateway 已重载".to_string())
}
}
@@ -839,7 +826,8 @@ pub async fn install_gateway() -> Result<String, String> {
/// 卸载 Gateway 服务
/// macOS: launchctl bootout + 删除 plist
/// Windows/Linux: openclaw gateway stop
/// Windows: 直接 taskkill
/// Linux: pkill
#[tauri::command]
pub fn uninstall_gateway() -> Result<String, String> {
#[cfg(target_os = "macos")]
@@ -859,10 +847,19 @@ pub fn uninstall_gateway() -> Result<String, String> {
fs::remove_file(&plist).map_err(|e| format!("删除 plist 失败: {e}"))?;
}
}
#[cfg(not(target_os = "macos"))]
#[cfg(target_os = "windows")]
{
// Windows/Linux: 停止 Gateway 服务
let _ = openclaw_command().args(["gateway", "stop"]).output();
// 直接杀死 gateway 相关的 node.exe 进程,不走慢 CLI
let _ = Command::new("taskkill")
.args(["/f", "/im", "node.exe", "/fi", "WINDOWTITLE eq openclaw*"])
.creation_flags(0x08000000)
.output();
}
#[cfg(target_os = "linux")]
{
let _ = Command::new("pkill")
.args(["-f", "openclaw.*gateway"])
.output();
}
Ok("Gateway 服务已卸载".to_string())

View File

@@ -98,6 +98,20 @@ fn cftunnel_bin() -> String {
}
}
/// 创建 cftunnel 命令Windows 上自动隐藏窗口
fn cftunnel_cmd(bin: &str) -> Command {
#[cfg(target_os = "windows")]
{
let mut cmd = Command::new(bin);
cmd.creation_flags(0x08000000);
cmd
}
#[cfg(not(target_os = "windows"))]
{
Command::new(bin)
}
}
/// 检测 cftunnel 进程是否在运行(平台相关的补充检测)
fn check_cftunnel_process() -> Option<(Option<u64>, bool)> {
#[cfg(target_os = "macos")]
@@ -178,7 +192,7 @@ pub fn get_cftunnel_status() -> Result<Value, String> {
result.insert("installed".into(), Value::Bool(true));
// 获取状态(单次 CLI 调用)
if let Ok(out) = Command::new(&bin).arg("status").output() {
if let Ok(out) = cftunnel_cmd(&bin).arg("status").output() {
let text = String::from_utf8_lossy(&out.stdout);
let status = parse_cftunnel_status(&text);
// 从 status 输出中提取版本号(如果有)
@@ -204,7 +218,7 @@ pub fn get_cftunnel_status() -> Result<Value, String> {
}
// 获取路由列表
if let Ok(out) = Command::new(&bin).arg("list").output() {
if let Ok(out) = cftunnel_cmd(&bin).arg("list").output() {
let text = String::from_utf8_lossy(&out.stdout);
let routes = parse_cftunnel_routes(&text);
result.insert("routes".into(), Value::Array(routes));
@@ -222,7 +236,7 @@ pub fn cftunnel_action(action: String) -> Result<(), String> {
"restart" => vec!["restart"],
_ => return Err(format!("不支持的操作: {action}")),
};
let output = Command::new(&bin)
let output = cftunnel_cmd(&bin)
.args(&args)
.output()
.map_err(|e| format!("执行 cftunnel {action} 失败: {e}"))?;
@@ -238,7 +252,7 @@ pub fn cftunnel_action(action: String) -> Result<(), String> {
pub fn get_cftunnel_logs(lines: Option<u32>) -> Result<String, String> {
let bin = cftunnel_bin();
let n = lines.unwrap_or(20).to_string();
let output = Command::new(&bin)
let output = cftunnel_cmd(&bin)
.args(["logs", "--tail", &n])
.output()
.map_err(|e| format!("读取 cftunnel 日志失败: {e}"))?;