Skip to content

命令执行 API ​

本文引用的源码文件

**本文引用的文件 **

目录 ​

  1. 文档目标与适用范围
  2. 架构总览
  3. 端点参考
  4. 安全机制
  5. WebSocket 实时输出
  6. 进程生命周期管理
  7. curl 示例
  8. WebSocket 客户端实现要点
  9. 性能调优建议
  10. 常见错误与调试技巧
  11. 结论

文档目标与适用范围 ​

本文面向需要调用本地 Agent 命令执行能力的开发者,重点说明:

  • 命令执行的 HTTP 接口行为。
  • 命令白名单、黑名单、Shell 检测、路径沙箱与安全分级。
  • 进程树终止、超时控制、输出截断与完成缓存。
  • WebSocket 实时输出、连接建立、消息格式与断开重连策略。
  • 运行中进程查询、停止与显式 daemon 化。
  • curl 使用方式、客户端实现注意事项和性能调优方向。

需要注意的运行时约束:

  • 本项目是 Chrome 扩展端与独立 Node.js Agent 的双进程架构。
  • Agent 源码修改后必须重启 Agent 进程,新接口才生效。
  • 命令执行能力由 Agent 端的 server.js 路由暴露,并由 executor.js 负责子进程调度,security.js 负责命令与路径安全检查。
  • 当前仓库中的命令执行入口是 /api/exec,并通过 wait 字段区分同步或异步语义;同时提供 /api/exec/stop、/api/exec/detach 等辅助接口。
  • 文档标题中提到的 /api/exec/run-sync、/api/exec/kill、/api/exec/list 并非当前代码中的实际路径,应理解为对 /api/exec 同步模式、/api/exec/stop、运行进程状态查询能力的概念性描述。

章节来源

架构总览 ​

命令执行的核心流程如下:

graph TB
Client["调用方<br/>浏览器扩展、脚本或外部工具"] --> Http["Agent HTTP 服务器<br/>/api/exec"]
Http --> Security["安全检查<br/>路径校验 + 命令分级"]
Security --> Executor["命令执行器<br/>spawn 子进程"]
Executor --> Process["操作系统进程树"]
Executor --> WsServer["WebSocket 服务器<br/>/ws/exec/{execId}"]
Process --> Output["stdout / stderr"]
Output --> WsServer
WsServer --> Client

图表来源

关键组件职责:

组件主要职责关键行为
HTTP 服务器解析请求、鉴权、路由到命令执行逻辑处理 /api/exec、/api/exec/stop、/api/exec/detach
安全检查模块路径白名单、核心敏感路径硬阻止、命令黑白灰名单返回 allow、confirm、deny
命令执行器创建子进程、流式输出、超时控制、进程列表支持异步、同步、WebSocket 回放、输出缓冲上限
进程树工具递归终止子进程及其孙进程POSIX 进程组信号、Windows taskkill

章节来源

端点参考 ​

/api/exec:命令执行入口 ​

该端点是命令执行的主要入口,支持两种模式:

参数类型是否必填含义
command字符串是要执行的完整命令
cwd字符串否工作目录;默认使用配置中的工作目录
wait布尔值否为真时走同步等待模式
force布尔值否为真时跳过灰名单确认,但黑名单仍不可绕过
timeoutMs数字否受管超时预算;未传时使用配置默认值

同步模式 ​

当 wait 为真时,HTTP 响应会阻塞直到命令结束,返回完整 stdout/stderr。

成功响应包含:

字段含义
success是否成功
level安全级别,通常为 allow
execId命令执行 ID
exitCode进程退出码
stdout标准输出
stderr标准错误
killed是否被主动终止
error可选错误信息

失败响应可能返回:

状态码含义
400缺少命令或请求体无效
403工作目录不在允许范围,或命令被黑名单拒绝
500命令执行异常

异步模式 ​

当 wait 为假或未传时,服务端立即启动命令并返回 execId 和 WebSocket 地址。

成功响应包含:

字段含义
success是否接受命令
level安全级别
execId命令执行 ID
wsUrlWebSocket 实时输出地址

安全确认模式 ​

如果命令命中灰名单且未设置 force,服务端不会直接执行,而是返回确认请求:

字段含义
success安全检查通过可继续
levelconfirm
reason触发确认的原因
command原始命令
cwd工作目录

调用方应在前端展示用户确认界面;确认后再次调用同一接口并设置 force: true。

章节来源

/api/exec/stop:终止进程 ​

该端点对应题目中的“终止进程”能力。

参数类型是否必填含义
execId字符串是要终止的命令执行 ID

成功响应:

字段含义
success是否成功发起终止
execId被终止的命令执行 ID

终止逻辑会尝试优雅终止,并在约 5 秒后强制终止,避免僵尸进程长期残留。

章节来源

/api/exec/detach:显式 daemon 化 ​

该端点用于显式声明命令进入后台运行模式:取消超时定时器,让进程继续运行。

参数类型是否必填含义
execId字符串是要 detach 的命令执行 ID

成功响应:

字段含义
success是否成功 detach
execId被 detach 的命令执行 ID

注意:detach 不是“查看运行进程”,它只是解除超时限制。

章节来源

运行进程查询 ​

当前代码没有独立的 /api/exec/list 端点,但运行进程信息会通过 /api/status/detail 返回。

在认证后的 /api/status/detail 响应中,包含:

字段含义
runningProcesses运行中进程列表
resourceUsageAgent 内存、CPU、运行时长等资源信息
commandTimeout命令超时配置
workdir当前工作目录
allowedPaths路径白名单

runningProcesses 每个元素包含:

字段含义
execId命令执行 ID
pid子进程 PID
command命令字符串
startTime开始时间戳
duration已运行毫秒数

章节来源

安全机制 ​

命令执行的安全机制分为两层:

  1. 路径层安全:限制命令的工作目录和文件访问范围。
  2. 命令层安全:对命令文本进行黑名单、灰名单和安全分级。

路径白名单与工作目录 ​

路径检查遵循以下优先级:

  1. 核心敏感路径硬阻止。
  2. 记忆存储目录放行。
  3. 工作目录始终放行。
  4. 配置中的 allowedPaths 白名单。
  5. 符号链接解析后再次校验。

核心敏感路径包括 Agent 配置文件、配对记录、日志目录、回收站目录等,任何情况下都不可访问。

工作目录是用户当前选定的操作目录,即使未出现在 allowedPaths 中也必须可访问。

章节来源

命令白名单、黑名单与灰名单 ​

命令安全检查采用三级分类:

级别含义是否可绕过
allow安全命令直接执行
confirm高风险但非绝对禁止可通过 force 跳过
deny绝对禁止不可绕过

黑名单包含:

  • 删除系统根目录、/dev、/proc、/sys。
  • 格式化磁盘、覆盖设备文件。
  • 覆盖 /etc/passwd、/etc/shadow、/etc/sudoers。
  • fork bomb。
  • shebang 直接执行。
  • 网络下载管道到 shell。
  • 修改根目录权限或属主。
  • Windows 格式化、分区、覆盖注册表蜂巢、覆盖 hosts 等。

灰名单包含:

  • sudo、doas、runas 提权。
  • 全局 npm 安装、pip 安装卸载。
  • 递归强制删除。
  • Git 强制推送。
  • 关机、重启、halt、poweroff。
  • 修改 /etc/hosts。
  • eval。
  • 命令替换(反引号、$( ))。
  • dd 写入、shred、truncate。
  • chmod/chown 危险权限变更。
  • curl/wget/nc/telnet/ssh/scp 等网络外联。
  • kill/pkill/killall/systemctl/launchctl/crontab/sysctl。
  • 解释器执行外部脚本。
  • Windows rmdir/del/icacls/takeown/reg/net/sc/taskkill 等高危命令。

黑名单在任何情况下都不允许执行;灰名单在未设置 force 时会要求用户确认。

章节来源

Shell 检测 ​

命令执行器会根据平台和环境选择 shell:

  • Windows:优先使用环境变量中的 bash、powershell、cmd;回退到 Git Bash 已知路径或 COMSPEC。
  • macOS:优先 zsh 或 bash;否则使用 /bin/zsh。
  • Linux:优先 bash、zsh、fish;否则探测 /bin/bash、/usr/bin/bash、/bin/sh。

选择 shell 时会检查路径是否存在,避免 MSYS/Git Bash 的 MSYS 风格路径在 Windows 上直接 spawn 失败。

章节来源

环境变量隔离 ​

命令执行使用安全环境变量白名单,不直接继承宿主全部环境。

白名单包含 PATH、HOME、USER、SHELL、LANG、编辑器相关变量、语言运行时变量、颜色控制变量等。

同时强制设置:

  • TERM=dumb
  • FORCE_COLOR=0

这能减少终端控制字符和颜色输出对日志和输出的干扰。

章节来源

WebSocket 实时输出 ​

连接建立 ​

异步命令执行成功后,响应中包含 wsUrl,格式为:

ws://{host}:{port}/ws/exec/{execId}

调用方应使用该 URL 建立 WebSocket 连接,订阅 stdout、stderr、exit、error 等事件。

如果命令已结束但客户端尚未连接,服务端会从已完成输出缓存中回放历史输出。

章节来源

消息格式 ​

WebSocket 消息统一为 JSON 字符串,常见类型如下:

type含义关键字段
stdout标准输出片段data、execId
stderr标准错误片段data、execId
stdout_truncatedstdout 超过缓冲区上限message、execId
stderr_truncatedstderr 超过缓冲区上限message、execId
exit进程结束exitCode、execId、killed、timedOut
error子进程错误error、execId

exitCode 为数字;若进程因错误无法获取退出码,可能为 -1。

killed 表示是否被主动终止。

timedOut 表示是否因超时策略被终止。

章节来源

断开重连处理 ​

WebSocket 客户端应实现以下重连策略:

  1. 连接建立后立即订阅所有消息。
  2. 收到 exit 后认为命令生命周期结束。
  3. 若连接断开且未收到 exit,应延迟重试连接。
  4. 重试连接后,若命令已结束,服务端会回放历史 stdout/stderr 和 exit 消息。
  5. 若命令仍在运行,新连接会加入现有进程的 WebSocket 客户端集合,接收后续输出。
  6. 不要仅根据 WS 断开就自动终止命令;只有显式调用 /api/exec/stop 或 /api/exec/detach 才改变进程行为。

章节来源

进程生命周期管理 ​

进程监控 ​

运行中的命令保存在内存映射中,键为 execId。

每个进程条目包含:

  • 子进程对象。
  • WebSocket 客户端集合。
  • stdout/stderr 缓冲区。
  • 是否截断标记。
  • 命令字符串。
  • 开始时间。
  • 基础超时值。
  • 是否受管模式。
  • 延长次数。
  • 本预算期内是否有输出。
  • 是否 detach。
  • 是否超时。

章节来源

资源清理 ​

输出缓冲区有上限,默认最大 5MB。

超过上限后会:

  1. 停止追加更多数据。
  2. 标记截断状态。
  3. 向 WebSocket 广播截断提示。
  4. 保留已有内容,避免无限增长导致内存泄漏。

命令完成后,结果会移入已完成缓存,供延迟连接的 WebSocket 客户端回放。

已完成缓存 TTL 为 30 秒,到期后清理。

章节来源

僵尸进程处理 ​

终止命令时,服务端会尽力递归终止整个进程树:

  • Unix/macOS:优先向进程组发送 SIGTERM;失败则回退到单进程;5 秒后强制 SIGKILL。
  • Windows:使用 taskkill /T /PID;失败后使用 /F /T /PID。

此外,process-tree.js 提供通用进程树终止工具,用于 npm 更新等场景,防止孙进程成为孤儿。

章节来源

超时控制 ​

超时控制有两种语义:

  1. 旧语义:未传入 timeoutMs 时,使用配置中的 commandTimeout;到期直接终止。
  2. 受管模式:传入 timeoutMs 后,超时到期先由策略函数裁决:
    • 如果本预算期内有 stdout/stderr 输出,则延长超时。
    • 如果完全无输出,视为挂起或静默失败,直接终止。
    • 延长次数最多 5 次。
    • 总预算封顶为 600000 毫秒。

同步模式下,额外增加 5 秒兜底,确保即使内层策略失效也能返回结果。

章节来源

curl 示例 ​

以下示例假设 Agent 监听在 http://127.0.0.1:18910,并已获取有效 Bearer Token。

同步命令执行 ​

bash
curl -X POST http://127.0.0.1:18910/api/exec \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "echo hello",
    "wait": true,
    "timeoutMs": 30000
  }'

异步命令执行 ​

bash
curl -X POST http://127.0.0.1:18910/api/exec \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "sleep 10 && echo done",
    "timeoutMs": 60000
  }'

需要确认的命令 ​

如果命令命中灰名单,首次调用会返回 level: confirm。确认后再次调用:

bash
curl -X POST http://127.0.0.1:18910/api/exec \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "ls -la",
    "force": true
  }'

终止命令 ​

bash
curl -X POST http://127.0.0.1:18910/api/exec/stop \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "execId": "YOUR_EXEC_ID"
  }'

显式 daemon 化 ​

bash
curl -X POST http://127.0.0.1:18910/api/exec/detach \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "execId": "YOUR_EXEC_ID"
  }'

查看运行进程 ​

bash
curl -X GET http://127.0.0.1:18910/api/status/detail \
  -H "Authorization: Bearer YOUR_TOKEN"

章节来源

WebSocket 客户端实现要点 ​

WebSocket 客户端不应只把连接当作一次性通道,而应按命令生命周期管理:

  1. 从 /api/exec 异步响应中取出 wsUrl。
  2. 建立 WebSocket 连接。
  3. 将收到的每条消息解析为 JSON。
  4. 根据 type 分发:
    • stdout:追加显示标准输出。
    • stderr:追加显示标准错误。
    • stdout_truncated / stderr_truncated:提示输出被截断。
    • exit:记录退出码、是否被杀、是否超时,并关闭连接。
    • error:记录子进程错误。
  5. 如果连接断开且未收到 exit,应指数退避重试连接。
  6. 重试成功后,若命令已结束,服务端会回放历史输出和 exit。
  7. 如果命令仍在运行,新连接会继续接收后续输出。
  8. 如果需要终止命令,调用 /api/exec/stop,而不是仅关闭 WebSocket。
  9. 如果需要后台运行,调用 /api/exec/detach。
sequenceDiagram
participant Caller as "调用方"
participant Http as "HTTP 服务器"
participant Exec as "命令执行器"
participant Ws as "WebSocket 服务器"
participant Proc as "子进程"
Caller->>Http : POST /api/exec
Http->>Exec : executeCommand(command, cwd, timeoutMs)
Exec->>Proc : spawn shell + command
Exec-->>Http : { execId, wsUrl }
Http-->>Caller : 异步启动响应
Caller->>Ws : 连接 wsUrl
Ws->>Exec : addWsClient(execId)
Proc-->>Ws : stdout/stderr 流
Ws-->>Caller : stdout/stderr 消息
Proc-->>Ws : close/error
Ws-->>Caller : exit/error 消息

图表来源

章节来源

性能调优建议 ​

合理设置超时 ​

  • 短命令建议使用较小的 timeoutMs,避免长时间占用资源。
  • 长任务建议使用受管模式,让策略函数根据输出动态延长超时。
  • 对于不需要实时输出的后台任务,可在适当时机调用 /api/exec/detach。

控制输出大小 ​

  • 大输出命令会产生大量 WebSocket 消息,建议分页消费或限制 UI 渲染长度。
  • 注意 5MB 输出缓冲上限;超过后会触发截断提示。
  • 同步模式会收集完整 stdout/stderr,不适合超大输出。

避免频繁刷新运行状态 ​

  • 运行进程列表来自内存映射,读取成本低,但仍应避免高频轮询 /api/status/detail。
  • 更推荐基于 WebSocket 的增量更新,只在必要时查询完整状态。

控制并发命令数量 ​

  • 每个命令都会创建子进程和至少两个流句柄。
  • 大量并发命令会增加 CPU、内存和文件描述符压力。
  • 建议在调用方侧做队列或限流。

避免重复连接 ​

  • 多个 WebSocket 客户端可以监听同一个 execId。
  • 如果只需要一个消费者,应避免重复连接造成重复渲染。

章节来源

常见错误与调试技巧 ​

缺少命令 ​

现象:返回 400,提示缺少命令。

原因:未传 command 或类型不是字符串。

处理:确保请求体包含合法命令字符串。

章节来源

工作目录不在允许范围 ​

现象:返回 403,提示工作目录检查失败。

原因:cwd 不在工作目录或 allowedPaths 白名单内,或命中核心敏感路径。

处理:使用配置中的工作目录,或将目标目录加入白名单。

章节来源

命令被黑名单拒绝 ​

现象:返回 403,level: deny。

原因:命令命中黑名单,如删除系统目录、格式化磁盘、覆盖敏感文件等。

处理:更换命令;黑名单不可通过 force 绕过。

章节来源

命令需要确认 ​

现象:返回 level: confirm。

原因:命令命中灰名单,例如 sudo、npm 全局安装、kill、curl、chmod 等。

处理:在前端展示确认提示;确认后再次调用并设置 force: true。

章节来源

命令执行失败 ​

现象:返回 500,提示命令执行失败。

原因:子进程启动失败、命令语法错误、权限不足等。

处理:查看 WebSocket 的 error 消息或同步模式的 error 字段;检查命令是否在目标系统可用。

章节来源

输出被截断 ​

现象:收到 stdout_truncated 或 stderr_truncated。

原因:输出超过 5MB 缓冲上限。

处理:后端过滤无用输出;前端提示用户输出已被截断;避免把超大命令输出直接渲染到 DOM。

章节来源

WebSocket 断开后无 exit ​

现象:连接断开,但没有收到 exit。

原因:网络闪断、浏览器扩展 Service Worker 被回收、客户端崩溃等。

处理:延迟重连;若命令已结束,服务端会回放历史输出;若命令仍在运行,新连接继续接收输出。

章节来源

命令未被终止 ​

现象:调用 /api/exec/stop 后进程仍存在。

原因:命令已结束、进程组不存在、Windows 下 taskkill 失败等。

处理:检查 success 字段;查看系统进程管理器;必要时结合系统级排查。

章节来源

结论 ​

命令执行 API 以 /api/exec 为核心入口,通过 wait 字段区分同步与异步模式,并通过 WebSocket 提供实时输出。安全机制由路径白名单、核心敏感路径硬阻止、命令黑名单/灰名单共同构成;超时控制支持旧语义和受管模式;进程终止支持跨平台递归终止。

使用建议:

  • 短命令优先使用同步模式。
  • 长命令优先使用异步模式 + WebSocket。
  • 高风险命令使用前展示用户确认。
  • 后台任务使用 /api/exec/detach。
  • 需要终止时使用 /api/exec/stop。
  • 通过 /api/status/detail 查看运行进程和资源使用情况。
  • 客户端实现健壮的重连、消息回放和生命周期管理逻辑。