Files
qiming/qimingclaw/crates/agent-electron-client/docs/operations/STARTUP-PORTS-DEEPCHECK.md

6.2 KiB
Raw Blame History

Deepcheck启动端口与统一 Bash 实现

1. 实现范围

  • shared/startupPorts.ts:端口默认值、配置键、resolvePortsFromSettings(getSetting)getPortsToCheck(ports, includeVite)
  • main/services/startupPorts.tsgetConfiguredPorts()getPortList()checkPortsInUse()isPortInUse()bash 优先Windows 回退 cmd+netstat
  • scripts/tools/check-port.sh单端口占用检查netstat/lsof供 bash 执行
  • scripts/tools/check-startup-ports.jsCLI读 DB、解析端口、调用 bash+check-port.sh 或回退 Node 内联

2. 正确性

2.1 三处脚本逻辑一致性

位置 来源 端口参数 Windows 分支 Unix 分支 输出/exit
check-port.sh 文件 $1 cmd //c "netstat -ano | findstr ":${port} "" lsof -t -i ":${port}" 占用: exit 0 + echo PID未占用: exit 1
main CHECK_PORT_SCRIPT 内嵌字符串 $1 同上(\":$1 \" 在 JS 中产生 ":$1 " lsof -t -i ":$1" 同左
脚本 读 check-port.sh spawnSync(..., '_', port) 由 .sh 决定 由 .sh 决定 同左
  • 结论.sh 与内嵌脚本语义一致;端口均通过 $1 传入,无注入(端口为数字的 String(port))。
  • 已修复CLI 原先用 execSync(bashPath, [args], options)Node 的 execSync 仅支持 (command, options),第二个参数被当成 options导致 bash 未按参数执行。已改为 spawnSync(bashPath, ['-c', scriptContent, '_', String(port)], options)

2.2 配置解析shared + 脚本)

  • step1_configstep1?.agentPort ?? defaultstep1?.fileServerPort ?? default。若 DB 存的是 {} 或缺失,则用默认值;若 agentPort: 0,会得到 0端口 0 在部分系统上表示“任选”,可能不符合预期,见 4.1)。
  • mcp_proxy_port:兼容 number 与 stringparseInt 失败或非整数时用默认值。
  • 脚本 DEFAULTS:与 shared/constants 数值一致,需人工与 shared 同步(见 4.2)。

2.3 端口占用结果

  • spawnSyncstatus === 0 表示脚本 exit 0端口占用stdout 取首行/最后一列解析 PID空 stdout 时 inUse: true, pid: undefined,行为合理。
  • 回退路径Windows 无 bash / 脚本无 .shmain 用 execSync + cmd脚本用 execSync + shell: true或 lsof行为与之前一致。

3. 平台与环境

3.1 Windows

  • 有 prepare-gitgetBundledGitBashPath() 返回 resources/git/bin/bash.exe(或 usr/binmain 与 CLI 均用该 bash 执行脚本;脚本内 OSTYPE=msys*,走 cmd+netstat+findstr一致。
  • 无 prepare-gitmain 回退 cmd+netstat脚本 winBashPath 不存在则回退 Node netstat逻辑一致。
  • 路径DB 路径 %USERPROFILE%\.qimingclaw\;脚本中 sqlite3 路径用正斜杠归一化,避免反斜杠转义问题。

3.2 macOS / Linux

  • main 与脚本均用系统 bash;脚本来自文件或内嵌,均包含 $OSTYPE 判断,非 msys/cygwin 走 lsof。
  • 无 bash(如 Alpine 仅 ashspawnSync('bash', ...) 会失败,当前实现将 status !== 0 视为未占用并返回 inUse: false,属保守回退,可接受;若需严格“未知”可再区分 error/status。

3.3 check-port.sh 被读入后的执行

  • 通过 bash -c "<scriptContent>" 执行时,首行 #!/usr/bin/env bash 被当作注释(# 起头),不影响执行,无需 strip。

4. 边界与改进建议

4.1 端口合法性

  • 当前未校验端口范围165535及 0。若配置了 agentPort: 0 或错误大数,会直接传给 startComputerServer/lsof/netstat。
  • 建议:在 resolvePortsFromSettings 或调用方对端口做范围校验,非法时回退默认或报错。

4.2 脚本与 shared 同步

  • check-startup-ports.js 的 DEFAULTS/LABELS 与 shared/constants、shared/startupPorts 需人工同步;脚本无法 require 编译后的 shared。
  • 建议:在脚本顶部注释中写明“与 shared/startupPorts.ts、constants 保持一致”;或考虑 build 时生成一份 ports-defaults.json 供脚本读取(可选)。

4.3 错误与超时

  • spawnSync 未设 timeout若 bash 或子命令卡住会阻塞。
  • 建议:若需在 UI 或敏感路径调用,可加 timeout 选项或异步封装。

4.4 安全性

  • 端口来自配置或常量,String(port) 后传入 spawn无用户自由输入无命令注入风险脚本内 $1 仅用于端口,且由调用方控制。
  • sqlite3 的 key 做单引号转义key 来自内部常量,风险可控。

5. 调用链与依赖

  • startup.tsgetConfiguredPorts().agent → ComputerServer 端口。
  • serviceManager.tsgetConfiguredPorts().fileServer → File Server 端口。
  • processHandlers.ts:动态 import getConfiguredPorts,取 fileServer → 重启时的 File Server 端口。
  • dependencies.ts:导出 getBundledGitBashPath(),供 main startupPorts 使用prepare-git 仅 Windows 下载并解压 Git 到 resources/git/

6. 测试建议

  • 单元resolvePortsFromSettings 用 mock getSetting 测默认值、step1 部分键、mcp 为 number/string/非法。
  • 集成:在 macOS 上运行 npm run check-portsnpm run check-ports:dev,确认有 bash + check-port.sh 时输出与 exit code 正确;关闭应用后再次检查,确认“未占用”与 exit 0。
  • Windows:在装有 prepare-git 与未装两种情况下各跑一次 CLI确认有 bash 时走脚本、无时走 netstat 回退。

7. 小结

状态
三处脚本逻辑一致(.sh / 内嵌 / CLI 调用方式) 一致
CLI 使用 spawnSync 传参(原 execSync 误用已修复) 已修复
配置解析与默认值 合理0 与范围未校验见 4.1
Windows 有/无 bash 回退 正确
Unix 使用 bash无 bash 时保守回退 可接受
安全与注入 端口与 key 受控
改进点 端口范围校验、DEFAULTS 同步方式、可选 timeout

Deepcheck 完成CLI 中 execSync 误用已改为 spawnSync。