目录
-
- 摘要
- [1. 引言:为什么需要远程命令执行?](#1. 引言:为什么需要远程命令执行?)
-
- [1.1 远程命令执行的现实需求](#1.1 远程命令执行的现实需求)
- [1.2 OpenClaw 命令执行架构总览](#1.2 OpenClaw 命令执行架构总览)
- [2. 命令执行基础:exec 工具详解](#2. 命令执行基础:exec 工具详解)
-
- [2.1 最简命令执行](#2.1 最简命令执行)
- [2.2 执行目标选择:host 参数](#2.2 执行目标选择:host 参数)
- [2.3 指定节点执行](#2.3 指定节点执行)
- [3. 执行模式:同步与异步](#3. 执行模式:同步与异步)
-
- [3.1 同步执行(默认模式)](#3.1 同步执行(默认模式))
- [3.2 异步执行:background 模式](#3.2 异步执行:background 模式)
- [3.3 yieldMs:延迟后台化](#3.3 yieldMs:延迟后台化)
- [3.4 process 工具:后台会话管理](#3.4 process 工具:后台会话管理)
- [4. 工作目录与环境变量](#4. 工作目录与环境变量)
-
- [4.1 指定工作目录](#4.1 指定工作目录)
- [4.2 环境变量覆盖](#4.2 环境变量覆盖)
- [4.3 Shell 选择](#4.3 Shell 选择)
- [5. 命令安全机制:白名单、审批与权限控制](#5. 命令安全机制:白名单、审批与权限控制)
-
- [5.1 安全模式概览](#5.1 安全模式概览)
- [5.2 白名单配置](#5.2 白名单配置)
- [5.3 审批机制(Approvals)](#5.3 审批机制(Approvals))
- [5.4 elevated 模式](#5.4 elevated 模式)
- [5.5 ask 模式](#5.5 ask 模式)
- [6. 超时与重试配置](#6. 超时与重试配置)
-
- [6.1 超时控制](#6.1 超时控制)
- [6.2 超时处理策略](#6.2 超时处理策略)
- [6.3 重试策略](#6.3 重试策略)
- [7. 输出捕获:stdout 与 stderr](#7. 输出捕获:stdout 与 stderr)
-
- [7.1 标准输出与标准错误](#7.1 标准输出与标准错误)
- [7.2 输出截断处理](#7.2 输出截断处理)
- [7.3 PTY 模式](#7.3 PTY 模式)
- [8. 实战案例一:远程服务管理](#8. 实战案例一:远程服务管理)
-
- [8.1 场景描述](#8.1 场景描述)
- [8.2 节点配置](#8.2 节点配置)
- [8.3 服务管理操作](#8.3 服务管理操作)
- [8.4 服务管理流程](#8.4 服务管理流程)
- [9. 实战案例二:批量脚本执行](#9. 实战案例二:批量脚本执行)
-
- [9.1 场景描述](#9.1 场景描述)
- [9.2 多节点批量执行](#9.2 多节点批量执行)
- [9.3 带错误处理的批量执行](#9.3 带错误处理的批量执行)
- [9.4 健康检查脚本](#9.4 健康检查脚本)
- [10. 实战案例三:系统状态监控](#10. 实战案例三:系统状态监控)
-
- [10.1 场景描述](#10.1 场景描述)
- [10.2 系统信息采集](#10.2 系统信息采集)
- [10.3 监控数据流](#10.3 监控数据流)
- [10.4 智能告警分析](#10.4 智能告警分析)
- [11. 节点配对与连接管理](#11. 节点配对与连接管理)
-
- [11.1 节点配对流程](#11.1 节点配对流程)
- [11.2 节点管理 CLI](#11.2 节点管理 CLI)
- [11.3 配对权限范围](#11.3 配对权限范围)
- [12. 高级系统操作](#12. 高级系统操作)
-
- [12.1 命令管道与组合](#12.1 命令管道与组合)
- [12.2 脚本文件执行](#12.2 脚本文件执行)
- [12.3 定时监控与 cron 替代](#12.3 定时监控与 cron 替代)
- [13. 完整参数参考](#13. 完整参数参考)
-
- [13.1 exec 工具参数一览](#13.1 exec 工具参数一览)
- [13.2 常用命令模式速查](#13.2 常用命令模式速查)
- [14. 最佳实践与常见问题](#14. 最佳实践与常见问题)
-
- [14.1 最佳实践清单](#14.1 最佳实践清单)
- [14.2 常见问题排查](#14.2 常见问题排查)
- [15. 架构全景图](#15. 架构全景图)
- [16. 总结与展望](#16. 总结与展望)
-
- [16.1 核心要点回顾](#16.1 核心要点回顾)
- [16.2 与传统方案对比](#16.2 与传统方案对比)
- 参考资料
摘要
本文深入解析 OpenClaw 的命令执行体系,从 exec 工具的基础用法到节点远程执行的高级模式,全面覆盖同步/异步执行、工作目录与环境变量配置、安全白名单与审批机制、超时与重试策略、stdout/stderr 输出捕获等核心主题。通过远程服务管理、批量脚本执行、系统状态监控三大实战案例,展示如何利用 OpenClaw 构建安全可靠的远程运维与自动化操作流水线。文章结合 Mermaid 架构图、配置表格与完整代码示例,帮助开发者快速掌握命令执行的最佳实践。🚀
1. 引言:为什么需要远程命令执行?
1.1 远程命令执行的现实需求
在云原生与分布式系统时代,运维人员和开发者经常需要在不同机器上执行命令------无论是查看服务器状态、重启服务、部署新版本,还是排查线上故障。传统的 SSH 手动操作虽然灵活,但存在效率低、无法批量执行、缺乏审计追踪、难以与 AI Agent 集成等问题。
OpenClaw 的 exec 工具和节点命令执行机制,为这些问题提供了统一的解决方案:
| 💡 需求场景 | 😩 传统痛点 | ✅ OpenClaw 方案 |
|---|---|---|
| 远程服务管理 | 多台机器逐一 SSH | 统一 Gateway 转发到节点 |
| 批量脚本执行 | 手动编写循环脚本 | AI Agent 自动编排 |
| 系统状态监控 | cron + 邮件告警 | 实时执行 + 智能分析 |
| 故障排查 | 登录机器翻日志 | 远程命令 + 结果解析 |
| 安全合规 | 无审计追踪 | 审批机制 + 白名单控制 |
1.2 OpenClaw 命令执行架构总览
OpenClaw 的命令执行体系是一个分层架构,从 AI Agent 到最终的目标机器,经过 Gateway 的安全审查与路由转发:
#mermaid-svg-6bNkQGkdgk6NYakX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6bNkQGkdgk6NYakX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6bNkQGkdgk6NYakX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6bNkQGkdgk6NYakX .error-icon{fill:#552222;}#mermaid-svg-6bNkQGkdgk6NYakX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6bNkQGkdgk6NYakX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6bNkQGkdgk6NYakX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6bNkQGkdgk6NYakX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6bNkQGkdgk6NYakX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6bNkQGkdgk6NYakX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6bNkQGkdgk6NYakX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6bNkQGkdgk6NYakX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6bNkQGkdgk6NYakX .marker.cross{stroke:#333333;}#mermaid-svg-6bNkQGkdgk6NYakX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6bNkQGkdgk6NYakX p{margin:0;}#mermaid-svg-6bNkQGkdgk6NYakX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6bNkQGkdgk6NYakX .cluster-label text{fill:#333;}#mermaid-svg-6bNkQGkdgk6NYakX .cluster-label span{color:#333;}#mermaid-svg-6bNkQGkdgk6NYakX .cluster-label span p{background-color:transparent;}#mermaid-svg-6bNkQGkdgk6NYakX .label text,#mermaid-svg-6bNkQGkdgk6NYakX span{fill:#333;color:#333;}#mermaid-svg-6bNkQGkdgk6NYakX .node rect,#mermaid-svg-6bNkQGkdgk6NYakX .node circle,#mermaid-svg-6bNkQGkdgk6NYakX .node ellipse,#mermaid-svg-6bNkQGkdgk6NYakX .node polygon,#mermaid-svg-6bNkQGkdgk6NYakX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6bNkQGkdgk6NYakX .rough-node .label text,#mermaid-svg-6bNkQGkdgk6NYakX .node .label text,#mermaid-svg-6bNkQGkdgk6NYakX .image-shape .label,#mermaid-svg-6bNkQGkdgk6NYakX .icon-shape .label{text-anchor:middle;}#mermaid-svg-6bNkQGkdgk6NYakX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6bNkQGkdgk6NYakX .rough-node .label,#mermaid-svg-6bNkQGkdgk6NYakX .node .label,#mermaid-svg-6bNkQGkdgk6NYakX .image-shape .label,#mermaid-svg-6bNkQGkdgk6NYakX .icon-shape .label{text-align:center;}#mermaid-svg-6bNkQGkdgk6NYakX .node.clickable{cursor:pointer;}#mermaid-svg-6bNkQGkdgk6NYakX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6bNkQGkdgk6NYakX .arrowheadPath{fill:#333333;}#mermaid-svg-6bNkQGkdgk6NYakX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6bNkQGkdgk6NYakX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6bNkQGkdgk6NYakX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6bNkQGkdgk6NYakX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6bNkQGkdgk6NYakX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6bNkQGkdgk6NYakX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6bNkQGkdgk6NYakX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6bNkQGkdgk6NYakX .cluster text{fill:#333;}#mermaid-svg-6bNkQGkdgk6NYakX .cluster span{color:#333;}#mermaid-svg-6bNkQGkdgk6NYakX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6bNkQGkdgk6NYakX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6bNkQGkdgk6NYakX rect.text{fill:none;stroke-width:0;}#mermaid-svg-6bNkQGkdgk6NYakX .icon-shape,#mermaid-svg-6bNkQGkdgk6NYakX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6bNkQGkdgk6NYakX .icon-shape p,#mermaid-svg-6bNkQGkdgk6NYakX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6bNkQGkdgk6NYakX .icon-shape .label rect,#mermaid-svg-6bNkQGkdgk6NYakX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6bNkQGkdgk6NYakX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6bNkQGkdgk6NYakX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6bNkQGkdgk6NYakX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} exec 调用
host=auto
沙箱活跃
无沙箱
host=node
system.run
stdout/stderr
🤖 AI Agent
Gateway
路由决策
📦 Sandbox
🖥️ Gateway Host
📱 Node Host
命令执行
📤 输出捕获
核心概念:
- Gateway:OpenClaw 的核心网关进程,接收消息、运行模型、路由工具调用
- Sandbox:隔离的沙箱运行环境,限制文件系统与网络访问
- Node Host :配对的远程节点,通过 WebSocket 连接到 Gateway,执行
system.run命令 - Exec Tool:AI Agent 可调用的命令执行工具,支持多种执行模式和安全策略
📖 更多架构细节参见 OpenClaw 官方文档 - Nodes
2. 命令执行基础:exec 工具详解
2.1 最简命令执行
OpenClaw 的 exec 工具是 AI Agent 执行 Shell 命令的核心入口。最基本的用法只需要一个 command 参数:
json
{
"tool": "exec",
"params": {
"command": "ls -la /home/user"
}
}
执行后返回的结果包含标准输出、标准错误、退出码和耗时信息:
json
{
"stdout": "total 32\ndrwxr-xr-x 5 user user 4096 Apr 20 10:00 .\n...",
"stderr": "",
"exitCode": 0,
"durationMs": 150
}
返回字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
stdout |
string | 标准输出内容 |
stderr |
string | 标准错误内容 |
exitCode |
number | 进程退出码(0 表示成功) |
durationMs |
number | 执行耗时(毫秒) |
2.2 执行目标选择:host 参数
exec 工具的 host 参数决定了命令在哪台机器上执行,这是理解 OpenClaw 命令执行体系的关键:
#mermaid-svg-eLZhuQ1IObd3h880{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eLZhuQ1IObd3h880 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eLZhuQ1IObd3h880 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eLZhuQ1IObd3h880 .error-icon{fill:#552222;}#mermaid-svg-eLZhuQ1IObd3h880 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eLZhuQ1IObd3h880 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eLZhuQ1IObd3h880 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eLZhuQ1IObd3h880 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eLZhuQ1IObd3h880 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eLZhuQ1IObd3h880 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eLZhuQ1IObd3h880 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eLZhuQ1IObd3h880 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eLZhuQ1IObd3h880 .marker.cross{stroke:#333333;}#mermaid-svg-eLZhuQ1IObd3h880 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eLZhuQ1IObd3h880 p{margin:0;}#mermaid-svg-eLZhuQ1IObd3h880 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eLZhuQ1IObd3h880 .cluster-label text{fill:#333;}#mermaid-svg-eLZhuQ1IObd3h880 .cluster-label span{color:#333;}#mermaid-svg-eLZhuQ1IObd3h880 .cluster-label span p{background-color:transparent;}#mermaid-svg-eLZhuQ1IObd3h880 .label text,#mermaid-svg-eLZhuQ1IObd3h880 span{fill:#333;color:#333;}#mermaid-svg-eLZhuQ1IObd3h880 .node rect,#mermaid-svg-eLZhuQ1IObd3h880 .node circle,#mermaid-svg-eLZhuQ1IObd3h880 .node ellipse,#mermaid-svg-eLZhuQ1IObd3h880 .node polygon,#mermaid-svg-eLZhuQ1IObd3h880 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eLZhuQ1IObd3h880 .rough-node .label text,#mermaid-svg-eLZhuQ1IObd3h880 .node .label text,#mermaid-svg-eLZhuQ1IObd3h880 .image-shape .label,#mermaid-svg-eLZhuQ1IObd3h880 .icon-shape .label{text-anchor:middle;}#mermaid-svg-eLZhuQ1IObd3h880 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eLZhuQ1IObd3h880 .rough-node .label,#mermaid-svg-eLZhuQ1IObd3h880 .node .label,#mermaid-svg-eLZhuQ1IObd3h880 .image-shape .label,#mermaid-svg-eLZhuQ1IObd3h880 .icon-shape .label{text-align:center;}#mermaid-svg-eLZhuQ1IObd3h880 .node.clickable{cursor:pointer;}#mermaid-svg-eLZhuQ1IObd3h880 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eLZhuQ1IObd3h880 .arrowheadPath{fill:#333333;}#mermaid-svg-eLZhuQ1IObd3h880 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eLZhuQ1IObd3h880 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eLZhuQ1IObd3h880 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eLZhuQ1IObd3h880 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eLZhuQ1IObd3h880 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eLZhuQ1IObd3h880 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eLZhuQ1IObd3h880 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eLZhuQ1IObd3h880 .cluster text{fill:#333;}#mermaid-svg-eLZhuQ1IObd3h880 .cluster span{color:#333;}#mermaid-svg-eLZhuQ1IObd3h880 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eLZhuQ1IObd3h880 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eLZhuQ1IObd3h880 rect.text{fill:none;stroke-width:0;}#mermaid-svg-eLZhuQ1IObd3h880 .icon-shape,#mermaid-svg-eLZhuQ1IObd3h880 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eLZhuQ1IObd3h880 .icon-shape p,#mermaid-svg-eLZhuQ1IObd3h880 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eLZhuQ1IObd3h880 .icon-shape .label rect,#mermaid-svg-eLZhuQ1IObd3h880 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eLZhuQ1IObd3h880 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eLZhuQ1IObd3h880 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eLZhuQ1IObd3h880 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} auto(默认)
是
否
sandbox
gateway
node
exec 调用
host 参数
沙箱是否活跃?
Sandbox
Gateway Host
指定 Node
| host 值 | 说明 | 适用场景 |
|---|---|---|
auto |
默认值;沙箱活跃时走沙箱,否则走 Gateway | 大多数情况 |
sandbox |
强制在沙箱中执行 | 需要隔离的不可信命令 |
gateway |
在 Gateway 主机上执行 | 需要访问主机资源 |
node |
在配对的远程节点上执行 | 远程设备管理 |
重要规则:
auto不是通配符,而是智能路由策略host=gateway仅在没有沙箱运行时允许host=node需要已配对的节点设备host不接受主机名,仅接受上述四个枚举值
2.3 指定节点执行
当 host=node 时,需要通过 node 参数指定目标节点:
json
{
"tool": "exec",
"params": {
"command": "systemctl status nginx",
"host": "node",
"node": "build-node-01"
}
}
节点通过 WebSocket 连接到 Gateway,以 role: "node" 注册并暴露命令表面(如 system.run、camera.*、device.* 等)。Gateway 将 exec 调用转发到对应节点的 system.run 接口执行。
3. 执行模式:同步与异步
3.1 同步执行(默认模式)
默认情况下,exec 工具同步执行命令,等待命令完成后返回结果。这是最常用的模式,适合短时间运行的命令:
json
{
"tool": "exec",
"params": {
"command": "ps aux | grep nginx",
"timeout": 10
}
}
同步执行的特点:
- ⏱️ 阻塞等待命令完成
- 📦 完整返回 stdout/stderr
- ⏰ 受
timeout参数控制(默认使用tools.exec.timeoutSec配置值) - 🎯 适合快速命令(ls、ps、cat 等)
3.2 异步执行:background 模式
对于长时间运行的任务(如模型训练、日志监控、编译构建),可以使用 background 参数将命令放入后台执行:
json
{
"tool": "exec",
"params": {
"command": "python3 train_model.py --epochs 100",
"background": true,
"workdir": "/opt/ml-project"
}
}
后台执行后,通过 process 工具管理运行中的会话:
json
{
"tool": "process",
"params": {
"action": "list"
}
}
3.3 yieldMs:延迟后台化
yieldMs 参数提供了一种更灵活的异步策略------先等待一段时间,如果命令在该时间内完成则直接返回结果,否则自动转入后台:
json
{
"tool": "exec",
"params": {
"command": "npm run build",
"yieldMs": 15000,
"workdir": "/home/user/frontend"
}
}
yieldMs 工作流程:
Shell 进程 exec 工具 AI Agent Shell 进程 exec 工具 AI Agent #mermaid-svg-PR9UhfoH8zpjAF8X{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PR9UhfoH8zpjAF8X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PR9UhfoH8zpjAF8X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PR9UhfoH8zpjAF8X .error-icon{fill:#552222;}#mermaid-svg-PR9UhfoH8zpjAF8X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PR9UhfoH8zpjAF8X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PR9UhfoH8zpjAF8X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PR9UhfoH8zpjAF8X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PR9UhfoH8zpjAF8X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PR9UhfoH8zpjAF8X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PR9UhfoH8zpjAF8X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PR9UhfoH8zpjAF8X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PR9UhfoH8zpjAF8X .marker.cross{stroke:#333333;}#mermaid-svg-PR9UhfoH8zpjAF8X svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PR9UhfoH8zpjAF8X p{margin:0;}#mermaid-svg-PR9UhfoH8zpjAF8X .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PR9UhfoH8zpjAF8X text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-PR9UhfoH8zpjAF8X .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PR9UhfoH8zpjAF8X .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-PR9UhfoH8zpjAF8X .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-PR9UhfoH8zpjAF8X .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-PR9UhfoH8zpjAF8X #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-PR9UhfoH8zpjAF8X .sequenceNumber{fill:white;}#mermaid-svg-PR9UhfoH8zpjAF8X #sequencenumber{fill:#333;}#mermaid-svg-PR9UhfoH8zpjAF8X #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-PR9UhfoH8zpjAF8X .messageText{fill:#333;stroke:none;}#mermaid-svg-PR9UhfoH8zpjAF8X .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PR9UhfoH8zpjAF8X .labelText,#mermaid-svg-PR9UhfoH8zpjAF8X .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-PR9UhfoH8zpjAF8X .loopText,#mermaid-svg-PR9UhfoH8zpjAF8X .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-PR9UhfoH8zpjAF8X .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PR9UhfoH8zpjAF8X .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-PR9UhfoH8zpjAF8X .noteText,#mermaid-svg-PR9UhfoH8zpjAF8X .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-PR9UhfoH8zpjAF8X .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PR9UhfoH8zpjAF8X .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PR9UhfoH8zpjAF8X .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PR9UhfoH8zpjAF8X .actorPopupMenu{position:absolute;}#mermaid-svg-PR9UhfoH8zpjAF8X .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-PR9UhfoH8zpjAF8X .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PR9UhfoH8zpjAF8X .actor-man circle,#mermaid-svg-PR9UhfoH8zpjAF8X line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-PR9UhfoH8zpjAF8X :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 可用 process 工具轮询 alt 命令在 15s 内完成 命令超过 15s exec(command, yieldMs=15000) 启动命令 返回结果 完整输出 后台会话信息 process(action=poll, sessionId=xxx) 当前输出/状态
三种模式对比:
| 模式 | 参数 | 等待行为 | 适用场景 |
|---|---|---|---|
| 同步 | 默认 | 完全等待 | 快速命令(<10s) |
| yieldMs | yieldMs=15000 |
等待 N ms 后后台化 | 可能较长的命令 |
| 后台 | background=true |
立即后台化 | 长时间任务 |
3.4 process 工具:后台会话管理
process 工具提供完整的后台会话生命周期管理:
| action | 说明 | 关键参数 |
|---|---|---|
list |
列出所有后台会话 | 无 |
poll |
轮询会话状态 | sessionId, timeout |
log |
获取会话日志 | sessionId, limit, offset |
write |
向会话写入数据 | sessionId, data |
send-keys |
发送按键 | sessionId, keys |
kill |
终止会话 | sessionId |
submit |
提交输入 | sessionId, text |
4. 工作目录与环境变量
4.1 指定工作目录
workdir 参数设置命令的执行目录,默认为当前工作目录(cwd):
json
{
"tool": "exec",
"params": {
"command": "git status",
"workdir": "/home/user/my-project"
}
}
这在操作特定项目时非常重要------比如在项目根目录执行 git pull、npm install 或 pytest,都需要正确的工作目录。
4.2 环境变量覆盖
env 参数允许为命令设置环境变量,这些变量会合并到继承的环境之上:
json
{
"tool": "exec",
"params": {
"command": "python3 app.py",
"workdir": "/opt/app",
"env": {
"NODE_ENV": "production",
"DATABASE_URL": "postgresql://localhost:5432/mydb",
"DEBUG": "false",
"PORT": "8080"
}
}
}
环境变量使用场景:
| 场景 | 示例变量 | 说明 |
|---|---|---|
| 运行环境切换 | NODE_ENV=production |
区分开发/生产环境 |
| 数据库连接 | DATABASE_URL=... |
避免硬编码连接串 |
| 调试控制 | DEBUG=false |
运行时开关 |
| 端口配置 | PORT=8080 |
服务监听端口 |
| API 密钥 | API_KEY=xxx |
注意不要记录到日志 |
⚠️ 安全提示:环境变量中的敏感信息(API Key、密码等)不应记录到日志或 MEMORY.md 中。OpenClaw 的审批机制会对此进行管控。
4.3 Shell 选择
OpenClaw 会智能选择 Shell 解释器:
- 非 Windows :优先使用
$SHELL环境变量;如果 Shell 是fish,则优先使用bash或sh(因为 fish 语法不兼容) - Windows :优先发现 PowerShell 7 (
pwsh),回退到 Windows PowerShell 5.1
5. 命令安全机制:白名单、审批与权限控制
5.1 安全模式概览
OpenClaw 的命令安全是一个多层防护体系,从配置级别的安全模式到运行时的审批流程:
#mermaid-svg-5tttGoqZYgKt5QjX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5tttGoqZYgKt5QjX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5tttGoqZYgKt5QjX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5tttGoqZYgKt5QjX .error-icon{fill:#552222;}#mermaid-svg-5tttGoqZYgKt5QjX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5tttGoqZYgKt5QjX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5tttGoqZYgKt5QjX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5tttGoqZYgKt5QjX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5tttGoqZYgKt5QjX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5tttGoqZYgKt5QjX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5tttGoqZYgKt5QjX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5tttGoqZYgKt5QjX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5tttGoqZYgKt5QjX .marker.cross{stroke:#333333;}#mermaid-svg-5tttGoqZYgKt5QjX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5tttGoqZYgKt5QjX p{margin:0;}#mermaid-svg-5tttGoqZYgKt5QjX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5tttGoqZYgKt5QjX .cluster-label text{fill:#333;}#mermaid-svg-5tttGoqZYgKt5QjX .cluster-label span{color:#333;}#mermaid-svg-5tttGoqZYgKt5QjX .cluster-label span p{background-color:transparent;}#mermaid-svg-5tttGoqZYgKt5QjX .label text,#mermaid-svg-5tttGoqZYgKt5QjX span{fill:#333;color:#333;}#mermaid-svg-5tttGoqZYgKt5QjX .node rect,#mermaid-svg-5tttGoqZYgKt5QjX .node circle,#mermaid-svg-5tttGoqZYgKt5QjX .node ellipse,#mermaid-svg-5tttGoqZYgKt5QjX .node polygon,#mermaid-svg-5tttGoqZYgKt5QjX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5tttGoqZYgKt5QjX .rough-node .label text,#mermaid-svg-5tttGoqZYgKt5QjX .node .label text,#mermaid-svg-5tttGoqZYgKt5QjX .image-shape .label,#mermaid-svg-5tttGoqZYgKt5QjX .icon-shape .label{text-anchor:middle;}#mermaid-svg-5tttGoqZYgKt5QjX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5tttGoqZYgKt5QjX .rough-node .label,#mermaid-svg-5tttGoqZYgKt5QjX .node .label,#mermaid-svg-5tttGoqZYgKt5QjX .image-shape .label,#mermaid-svg-5tttGoqZYgKt5QjX .icon-shape .label{text-align:center;}#mermaid-svg-5tttGoqZYgKt5QjX .node.clickable{cursor:pointer;}#mermaid-svg-5tttGoqZYgKt5QjX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5tttGoqZYgKt5QjX .arrowheadPath{fill:#333333;}#mermaid-svg-5tttGoqZYgKt5QjX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5tttGoqZYgKt5QjX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5tttGoqZYgKt5QjX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5tttGoqZYgKt5QjX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5tttGoqZYgKt5QjX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5tttGoqZYgKt5QjX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5tttGoqZYgKt5QjX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5tttGoqZYgKt5QjX .cluster text{fill:#333;}#mermaid-svg-5tttGoqZYgKt5QjX .cluster span{color:#333;}#mermaid-svg-5tttGoqZYgKt5QjX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5tttGoqZYgKt5QjX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5tttGoqZYgKt5QjX rect.text{fill:none;stroke-width:0;}#mermaid-svg-5tttGoqZYgKt5QjX .icon-shape,#mermaid-svg-5tttGoqZYgKt5QjX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5tttGoqZYgKt5QjX .icon-shape p,#mermaid-svg-5tttGoqZYgKt5QjX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5tttGoqZYgKt5QjX .icon-shape .label rect,#mermaid-svg-5tttGoqZYgKt5QjX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5tttGoqZYgKt5QjX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5tttGoqZYgKt5QjX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5tttGoqZYgKt5QjX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} deny
allowlist
是
否
auto
安全命令
需审批
批准
拒绝
full
exec 调用
security 模式
❌ 拒绝执行
命令在白名单?
✅ 直接执行
❌ 拒绝执行
自动审查
🔔 请求人工审批
⚠️ 无限制执行
安全模式详解:
| 模式 | 值 | 行为 | 风险等级 |
|---|---|---|---|
| 拒绝 | deny |
禁止所有命令执行 | 🟢 无风险 |
| 白名单 | allowlist |
仅允许白名单中的命令 | 🟢 低风险 |
| 自动 | auto |
安全命令直接执行,其余走审批 | 🟡 中风险 |
| 询问 | ask |
每次执行都需人工确认 | 🟡 中风险 |
| 完全 | full |
无任何限制 | 🔴 高风险 |
5.2 白名单配置
白名单模式通过 tools.exec.mode 配置,只允许预定义的安全命令执行:
json5
// ~/.openclaw/openclaw.json
{
tools: {
exec: {
mode: "allowlist",
allowlist: [
"ls", "cat", "head", "tail", "grep", "find",
"ps", "top", "df", "du", "free", "uptime",
"git", "node", "npm", "python3"
]
}
}
}
5.3 审批机制(Approvals)
对于 auto 模式下无法自动判定安全性的命令,OpenClaw 会发起人工审批请求。审批记录存储在 ~/.openclaw/exec-approvals.json 中。
节点执行的审批规则:
- 审批绑定了精确的请求上下文(命令、工作目录、环境变量)
- 对于直接 Shell/运行时文件执行,OpenClaw 会尽力绑定一个具体的本地文件操作数,如果该文件在执行前发生变化,则拒绝执行
- 如果 OpenClaw 无法识别唯一的具体本地文件(如解释器/运行时命令),则拒绝审批而非假装覆盖所有运行时语义
审批流程示例:
Agent 请求执行: sudo systemctl restart nginx
↓
Gateway 检查: security=auto, 命令不在安全白名单
↓
发起审批请求: /approve abc123
↓
用户在聊天中回复: /approve abc123
↓
命令执行, 返回结果
5.4 elevated 模式
elevated 参数允许命令逃逸沙箱,在配置的主机路径上执行:
json
{
"tool": "exec",
"params": {
"command": "systemctl restart myapp",
"elevated": true
}
}
elevated 的行为:
- 逃逸沙箱到 Gateway 主机(默认)或 Node 主机
- 仅在当前会话/提供商启用了 elevated 访问时可用
security=full仅在 elevated 解析为full时强制生效- 需要操作者显式授予 elevated 权限
5.5 ask 模式
ask 参数控制审批的触发时机:
| ask 值 | 说明 |
|---|---|
off |
不请求审批 |
on-miss |
自动审查未通过时请求审批 |
always |
每次执行都请求审批 |
📖 安全配置详情参见 OpenClaw 官方文档 - Security
6. 超时与重试配置
6.1 超时控制
超时是防止命令无限挂起的关键机制。OpenClaw 提供多级超时控制:
json
{
"tool": "exec",
"params": {
"command": "python3 long_running_task.py",
"timeout": 60
}
}
超时参数说明:
| 参数 | 级别 | 默认值 | 说明 |
|---|---|---|---|
timeout |
调用级 | tools.exec.timeoutSec |
本次调用的超时秒数 |
tools.exec.timeoutSec |
配置级 | 120 | 全局默认超时 |
timeout: 0 |
特殊 | 无限 | 禁用进程超时(慎用) |
超时适用范围:
超时机制覆盖所有执行模式:
- ✅ 前台执行
- ✅ 后台执行(
background=true) - ✅ yieldMs 模式
- ✅ Gateway 主机执行
- ✅ Sandbox 执行
- ✅ Node
system.run执行
6.2 超时处理策略
#mermaid-svg-cSjSYl1dwpXYDsI9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cSjSYl1dwpXYDsI9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cSjSYl1dwpXYDsI9 .error-icon{fill:#552222;}#mermaid-svg-cSjSYl1dwpXYDsI9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cSjSYl1dwpXYDsI9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cSjSYl1dwpXYDsI9 .marker.cross{stroke:#333333;}#mermaid-svg-cSjSYl1dwpXYDsI9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cSjSYl1dwpXYDsI9 p{margin:0;}#mermaid-svg-cSjSYl1dwpXYDsI9 defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-cSjSYl1dwpXYDsI9 g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-cSjSYl1dwpXYDsI9 g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-cSjSYl1dwpXYDsI9 g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-cSjSYl1dwpXYDsI9 g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-cSjSYl1dwpXYDsI9 g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-cSjSYl1dwpXYDsI9 .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-cSjSYl1dwpXYDsI9 .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-cSjSYl1dwpXYDsI9 .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cSjSYl1dwpXYDsI9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cSjSYl1dwpXYDsI9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cSjSYl1dwpXYDsI9 .edgeLabel .label text{fill:#333;}#mermaid-svg-cSjSYl1dwpXYDsI9 .label div .edgeLabel{color:#333;}#mermaid-svg-cSjSYl1dwpXYDsI9 .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-cSjSYl1dwpXYDsI9 .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-cSjSYl1dwpXYDsI9 .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-cSjSYl1dwpXYDsI9 .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-cSjSYl1dwpXYDsI9 .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-cSjSYl1dwpXYDsI9 .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cSjSYl1dwpXYDsI9 #statediagram-barbEnd{fill:#333333;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .cluster-label,#mermaid-svg-cSjSYl1dwpXYDsI9 .nodeLabel{color:#131300;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-cSjSYl1dwpXYDsI9 .note-edge{stroke-dasharray:5;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-note text{fill:black;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram-note .nodeLabel{color:black;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagram .edgeLabel{color:red;}#mermaid-svg-cSjSYl1dwpXYDsI9 #dependencyStart,#mermaid-svg-cSjSYl1dwpXYDsI9 #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-cSjSYl1dwpXYDsI9 .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cSjSYl1dwpXYDsI9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} exec 调用
正常退出
超时触发
手动 kill
返回结果
返回超时错误
返回终止信息
Running
Completed
TimedOut
Killed
当命令超时时,OpenClaw 会:
- 向进程发送 SIGTERM 信号
- 等待短暂的优雅关闭窗口
- 如果进程仍未退出,发送 SIGKILL 强制终止
- 返回超时错误信息,包含已捕获的部分输出
6.3 重试策略
虽然 exec 工具本身不内置重试机制,但可以通过 AI Agent 的逻辑实现智能重试:
python
# AI Agent 中的重试逻辑(伪代码)
max_retries = 3
for attempt in range(max_retries):
result = exec(command="curl -s https://api.example.com/health")
if result.exitCode == 0:
break
if attempt < max_retries - 1:
wait(seconds=2 ** attempt) # 指数退避
重试策略建议:
| 策略 | 退避公式 | 适用场景 |
|---|---|---|
| 固定间隔 | wait = 5s |
简单重试 |
| 线性增长 | wait = attempt * 5s |
网络请求 |
| 指数退避 | wait = 2^attempt s |
API 调用 |
| 指数退避+抖动 | wait = 2^attempt + random() |
分布式系统 |
7. 输出捕获:stdout 与 stderr
7.1 标准输出与标准错误
OpenClaw 完整捕获命令的 stdout 和 stderr 输出。理解两者的区别对于正确处理命令结果至关重要:
| 流 | 用途 | 示例 |
|---|---|---|
stdout |
正常输出 | ls -la 的文件列表 |
stderr |
错误/诊断信息 | 编译警告、错误提示 |
7.2 输出截断处理
对于产生大量输出的命令,OpenClaw 会对输出进行截断以避免内存溢出。处理大输出时的最佳实践:
json
{
"tool": "exec",
"params": {
"command": "cat /var/log/nginx/access.log | tail -n 1000"
}
}
大输出处理策略:
| 策略 | 命令示例 | 说明 |
|---|---|---|
| 限制行数 | tail -n 100 |
只取最后 N 行 |
| 过滤关键信息 | grep ERROR |
只看错误行 |
| 分页读取 | head -n 1000 |
分批读取 |
| 重定向到文件 | > /tmp/output.txt |
输出到文件后用 read 工具读取 |
| 统计摘要 | wc -l, awk |
只看统计信息 |
7.3 PTY 模式
某些命令需要 TTY(伪终端)才能正常工作,如交互式 CLI、终端 UI 应用等。OpenClaw 通过 pty 参数支持 PTY 模式:
json
{
"tool": "exec",
"params": {
"command": "htop",
"pty": true
}
}
PTY 模式适用场景:
- 🖥️ 终端 UI 应用(htop、vim、nano)
- 🤖 交互式编程代理(需要 TTY 的 CLI 工具)
- 📝 需要颜色输出的命令
- 🔑 交互式登录/认证流程
8. 实战案例一:远程服务管理
8.1 场景描述
假设我们有一台远程服务器(节点名称 prod-server),需要通过 OpenClaw 管理其上的 Nginx 服务。包括查看状态、重启服务、检查配置、查看访问日志等操作。
8.2 节点配置
首先,在远程服务器上启动 Node Host 并连接到 Gateway:
bash
# 在远程服务器上执行
# 方式一:直接连接(Gateway 绑定到 0.0.0.0)
openclaw node run \
--host gateway.example.com \
--port 18789 \
--display-name "prod-server"
# 方式二:通过 SSH 隧道连接(Gateway 绑定到 loopback)
# Terminal A:建立 SSH 隧道
ssh -N -L 18790:127.0.0.1:18789 user@gateway.example.com
# Terminal B:通过隧道连接
export OPENCLAW_GATEWAY_TOKEN="your-gateway-token"
openclaw node run \
--host 127.0.0.1 \
--port 18790 \
--display-name "prod-server"
这段代码展示了两种节点连接方式。方式一适用于 Gateway 直接暴露在网络上的场景;方式二通过 SSH 本地端口转发,将远程 Gateway 的 18789 端口映射到本地 18790,然后 Node Host 连接本地隧道端口。SSH 隧道方式更安全,因为 Gateway 可以保持 loopback 绑定,不直接暴露到公网。OPENCLAW_GATEWAY_TOKEN 环境变量用于节点认证。
8.3 服务管理操作
json
// 检查 Nginx 服务状态
{
"tool": "exec",
"params": {
"command": "systemctl status nginx --no-pager",
"host": "node",
"node": "prod-server",
"timeout": 10
}
}
// 重启 Nginx 服务(需要 elevated 权限)
{
"tool": "exec",
"params": {
"command": "sudo systemctl restart nginx",
"host": "node",
"node": "prod-server",
"elevated": true,
"timeout": 30
}
}
// 验证 Nginx 配置语法
{
"tool": "exec",
"params": {
"command": "sudo nginx -t",
"host": "node",
"node": "prod-server",
"timeout": 10
}
}
// 查看最近的访问日志
{
"tool": "exec",
"params": {
"command": "tail -n 50 /var/log/nginx/access.log",
"host": "node",
"node": "prod-server",
"timeout": 10
}
}
以上四个命令覆盖了服务管理的核心操作。systemctl status 查看服务当前状态;systemctl restart 需要提升权限(elevated=true);nginx -t 验证配置文件语法是否正确,这是重载配置前的必要检查;tail 命令查看最近的访问日志。每个命令都设置了合理的超时时间,防止命令挂起。
8.4 服务管理流程
#mermaid-svg-9FRku5pXTUnC94Aq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9FRku5pXTUnC94Aq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9FRku5pXTUnC94Aq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9FRku5pXTUnC94Aq .error-icon{fill:#552222;}#mermaid-svg-9FRku5pXTUnC94Aq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9FRku5pXTUnC94Aq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9FRku5pXTUnC94Aq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9FRku5pXTUnC94Aq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9FRku5pXTUnC94Aq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9FRku5pXTUnC94Aq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9FRku5pXTUnC94Aq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9FRku5pXTUnC94Aq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9FRku5pXTUnC94Aq .marker.cross{stroke:#333333;}#mermaid-svg-9FRku5pXTUnC94Aq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9FRku5pXTUnC94Aq p{margin:0;}#mermaid-svg-9FRku5pXTUnC94Aq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9FRku5pXTUnC94Aq .cluster-label text{fill:#333;}#mermaid-svg-9FRku5pXTUnC94Aq .cluster-label span{color:#333;}#mermaid-svg-9FRku5pXTUnC94Aq .cluster-label span p{background-color:transparent;}#mermaid-svg-9FRku5pXTUnC94Aq .label text,#mermaid-svg-9FRku5pXTUnC94Aq span{fill:#333;color:#333;}#mermaid-svg-9FRku5pXTUnC94Aq .node rect,#mermaid-svg-9FRku5pXTUnC94Aq .node circle,#mermaid-svg-9FRku5pXTUnC94Aq .node ellipse,#mermaid-svg-9FRku5pXTUnC94Aq .node polygon,#mermaid-svg-9FRku5pXTUnC94Aq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9FRku5pXTUnC94Aq .rough-node .label text,#mermaid-svg-9FRku5pXTUnC94Aq .node .label text,#mermaid-svg-9FRku5pXTUnC94Aq .image-shape .label,#mermaid-svg-9FRku5pXTUnC94Aq .icon-shape .label{text-anchor:middle;}#mermaid-svg-9FRku5pXTUnC94Aq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9FRku5pXTUnC94Aq .rough-node .label,#mermaid-svg-9FRku5pXTUnC94Aq .node .label,#mermaid-svg-9FRku5pXTUnC94Aq .image-shape .label,#mermaid-svg-9FRku5pXTUnC94Aq .icon-shape .label{text-align:center;}#mermaid-svg-9FRku5pXTUnC94Aq .node.clickable{cursor:pointer;}#mermaid-svg-9FRku5pXTUnC94Aq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9FRku5pXTUnC94Aq .arrowheadPath{fill:#333333;}#mermaid-svg-9FRku5pXTUnC94Aq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9FRku5pXTUnC94Aq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9FRku5pXTUnC94Aq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9FRku5pXTUnC94Aq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9FRku5pXTUnC94Aq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9FRku5pXTUnC94Aq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9FRku5pXTUnC94Aq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9FRku5pXTUnC94Aq .cluster text{fill:#333;}#mermaid-svg-9FRku5pXTUnC94Aq .cluster span{color:#333;}#mermaid-svg-9FRku5pXTUnC94Aq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9FRku5pXTUnC94Aq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9FRku5pXTUnC94Aq rect.text{fill:none;stroke-width:0;}#mermaid-svg-9FRku5pXTUnC94Aq .icon-shape,#mermaid-svg-9FRku5pXTUnC94Aq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9FRku5pXTUnC94Aq .icon-shape p,#mermaid-svg-9FRku5pXTUnC94Aq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9FRku5pXTUnC94Aq .icon-shape .label rect,#mermaid-svg-9FRku5pXTUnC94Aq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9FRku5pXTUnC94Aq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9FRku5pXTUnC94Aq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9FRku5pXTUnC94Aq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
📋 检查状态
服务正常?
✅ 无需操作
🔄 重启服务
🔍 验证配置
配置正确?
📊 查看日志
🔧 修复配置
✅ 完成恢复
9. 实战案例二:批量脚本执行
9.1 场景描述
在多节点环境中,经常需要在所有节点上执行相同的脚本------比如更新系统包、部署新版本应用、运行健康检查等。OpenClaw 的 exec 工具配合 AI Agent 的编排能力,可以轻松实现批量操作。
9.2 多节点批量执行
假设我们有三个节点:web-01、web-02、web-03,需要在这些节点上执行部署脚本:
json
// 在 web-01 上拉取最新代码并重启
{
"tool": "exec",
"params": {
"command": "cd /opt/app && git pull origin main && npm install && npm run build && sudo systemctl restart myapp",
"host": "node",
"node": "web-01",
"timeout": 300,
"workdir": "/opt/app"
}
}
// 在 web-02 上执行相同操作
{
"tool": "exec",
"params": {
"command": "cd /opt/app && git pull origin main && npm install && npm run build && sudo systemctl restart myapp",
"host": "node",
"node": "web-02",
"timeout": 300,
"workdir": "/opt/app"
}
}
// 在 web-03 上执行相同操作
{
"tool": "exec",
"params": {
"command": "cd /opt/app && git pull origin main && npm install && npm run build && sudo systemctl restart myapp",
"host": "node",
"node": "web-03",
"timeout": 300,
"workdir": "/opt/app"
}
}
这个批量部署示例展示了在三个 Web 节点上执行完整部署流水线:拉取代码、安装依赖、构建项目、重启服务。每个命令设置了 300 秒超时以适应构建时间。在实际生产中,AI Agent 会串行或并行发起这些调用,并根据每个节点的执行结果决定是否继续。
9.3 带错误处理的批量执行
更健壮的批量执行应该包含错误处理和回滚逻辑:
#mermaid-svg-Vyf5xmJCBzHPJrx2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .error-icon{fill:#552222;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .marker.cross{stroke:#333333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Vyf5xmJCBzHPJrx2 p{margin:0;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .cluster-label text{fill:#333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .cluster-label span{color:#333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .cluster-label span p{background-color:transparent;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .label text,#mermaid-svg-Vyf5xmJCBzHPJrx2 span{fill:#333;color:#333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .node rect,#mermaid-svg-Vyf5xmJCBzHPJrx2 .node circle,#mermaid-svg-Vyf5xmJCBzHPJrx2 .node ellipse,#mermaid-svg-Vyf5xmJCBzHPJrx2 .node polygon,#mermaid-svg-Vyf5xmJCBzHPJrx2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .rough-node .label text,#mermaid-svg-Vyf5xmJCBzHPJrx2 .node .label text,#mermaid-svg-Vyf5xmJCBzHPJrx2 .image-shape .label,#mermaid-svg-Vyf5xmJCBzHPJrx2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .rough-node .label,#mermaid-svg-Vyf5xmJCBzHPJrx2 .node .label,#mermaid-svg-Vyf5xmJCBzHPJrx2 .image-shape .label,#mermaid-svg-Vyf5xmJCBzHPJrx2 .icon-shape .label{text-align:center;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .node.clickable{cursor:pointer;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .arrowheadPath{fill:#333333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Vyf5xmJCBzHPJrx2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vyf5xmJCBzHPJrx2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Vyf5xmJCBzHPJrx2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .cluster text{fill:#333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .cluster span{color:#333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Vyf5xmJCBzHPJrx2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .icon-shape,#mermaid-svg-Vyf5xmJCBzHPJrx2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .icon-shape p,#mermaid-svg-Vyf5xmJCBzHPJrx2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .icon-shape .label rect,#mermaid-svg-Vyf5xmJCBzHPJrx2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vyf5xmJCBzHPJrx2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Vyf5xmJCBzHPJrx2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Vyf5xmJCBzHPJrx2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
是
否
🚀 开始批量部署
📦 拉取代码
所有节点成功?
📥 安装依赖
🔄 回滚代码
所有节点成功?
🔨 构建项目
所有节点成功?
🔄 重启服务
所有节点健康?
✅ 部署完成
⚠️ 部分节点异常
9.4 健康检查脚本
部署完成后,通过批量健康检查验证所有节点:
json
// 检查 web-01 健康状态
{
"tool": "exec",
"params": {
"command": "curl -sf http://localhost:8080/health && echo 'HEALTHY' || echo 'UNHEALTHY'",
"host": "node",
"node": "web-01",
"timeout": 10
}
}
// 检查 web-02 健康状态
{
"tool": "exec",
"params": {
"command": "curl -sf http://localhost:8080/health && echo 'HEALTHY' || echo 'UNHEALTHY'",
"host": "node",
"node": "web-02",
"timeout": 10
}
}
// 检查 web-03 健康状态
{
"tool": "exec",
"params": {
"command": "curl -sf http://localhost:8080/health && echo 'HEALTHY' || echo 'UNHEALTHY'",
"host": "node",
"node": "web-03",
"timeout": 10
}
}
健康检查使用 curl -sf 访问本地健康端点。-s 静默模式不输出进度,-f 在 HTTP 错误时返回非零退出码。如果健康检查返回 200,输出 HEALTHY;否则输出 UNHEALTHY。AI Agent 可以根据所有节点的健康状态决定是否需要回滚或告警。
10. 实战案例三:系统状态监控
10.1 场景描述
持续监控系统状态是运维的核心任务。通过 OpenClaw 的 exec 工具,AI Agent 可以定期在远程节点上执行监控命令,收集系统指标并智能分析。
10.2 系统信息采集
以下命令组合覆盖了系统监控的关键维度:
json
// CPU 使用率
{
"tool": "exec",
"params": {
"command": "top -bn1 | head -n 5",
"host": "node",
"node": "prod-server",
"timeout": 10
}
}
// 内存使用情况
{
"tool": "exec",
"params": {
"command": "free -h",
"host": "node",
"node": "prod-server",
"timeout": 10
}
}
// 磁盘使用情况
{
"tool": "exec",
"params": {
"command": "df -h | grep -v tmpfs",
"host": "node",
"node": "prod-server",
"timeout": 10
}
}
// 系统负载与运行时间
{
"tool": "exec",
"params": {
"command": "uptime",
"host": "node",
"node": "prod-server",
"timeout": 10
}
}
// 关键进程状态
{
"tool": "exec",
"params": {
"command": "ps aux | grep -E 'nginx|node|python|redis|postgres' | grep -v grep",
"host": "node",
"node": "prod-server",
"timeout": 10
}
}
这组命令采集了 CPU、内存、磁盘、负载和关键进程五个维度的系统状态。top -bn1 以批处理模式运行一次 top 命令,head -n 5 只取前 5 行摘要;free -h 以人类可读格式显示内存;df -h 显示磁盘使用,grep -v tmpfs 过滤掉临时文件系统;uptime 显示系统负载和运行时间;最后的 ps aux 组合过滤出关键服务的进程信息。
10.3 监控数据流
目标系统 Node Host Gateway AI Agent 目标系统 Node Host Gateway AI Agent #mermaid-svg-9wTXUPnhQfLaNXGB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9wTXUPnhQfLaNXGB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9wTXUPnhQfLaNXGB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9wTXUPnhQfLaNXGB .error-icon{fill:#552222;}#mermaid-svg-9wTXUPnhQfLaNXGB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9wTXUPnhQfLaNXGB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9wTXUPnhQfLaNXGB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9wTXUPnhQfLaNXGB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9wTXUPnhQfLaNXGB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9wTXUPnhQfLaNXGB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9wTXUPnhQfLaNXGB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9wTXUPnhQfLaNXGB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9wTXUPnhQfLaNXGB .marker.cross{stroke:#333333;}#mermaid-svg-9wTXUPnhQfLaNXGB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9wTXUPnhQfLaNXGB p{margin:0;}#mermaid-svg-9wTXUPnhQfLaNXGB .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9wTXUPnhQfLaNXGB text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-9wTXUPnhQfLaNXGB .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-9wTXUPnhQfLaNXGB .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-9wTXUPnhQfLaNXGB .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-9wTXUPnhQfLaNXGB .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-9wTXUPnhQfLaNXGB #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-9wTXUPnhQfLaNXGB .sequenceNumber{fill:white;}#mermaid-svg-9wTXUPnhQfLaNXGB #sequencenumber{fill:#333;}#mermaid-svg-9wTXUPnhQfLaNXGB #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-9wTXUPnhQfLaNXGB .messageText{fill:#333;stroke:none;}#mermaid-svg-9wTXUPnhQfLaNXGB .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9wTXUPnhQfLaNXGB .labelText,#mermaid-svg-9wTXUPnhQfLaNXGB .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-9wTXUPnhQfLaNXGB .loopText,#mermaid-svg-9wTXUPnhQfLaNXGB .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-9wTXUPnhQfLaNXGB .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-9wTXUPnhQfLaNXGB .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-9wTXUPnhQfLaNXGB .noteText,#mermaid-svg-9wTXUPnhQfLaNXGB .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-9wTXUPnhQfLaNXGB .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9wTXUPnhQfLaNXGB .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9wTXUPnhQfLaNXGB .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9wTXUPnhQfLaNXGB .actorPopupMenu{position:absolute;}#mermaid-svg-9wTXUPnhQfLaNXGB .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-9wTXUPnhQfLaNXGB .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9wTXUPnhQfLaNXGB .actor-man circle,#mermaid-svg-9wTXUPnhQfLaNXGB line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-9wTXUPnhQfLaNXGB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 智能分析所有指标 生成监控报告 exec(host=node, command=top) 转发 system.run 执行 top -bn1 CPU 数据 stdout + exitCode 返回结果 exec(host=node, command=free) 转发 system.run 执行 free -h 内存数据 stdout + exitCode 返回结果
10.4 智能告警分析
AI Agent 的独特优势在于能对监控数据进行智能分析,而不仅仅是简单地采集和展示:
| 📊 监控指标 | ⚠️ 告警条件 | 🤖 AI 分析能力 |
|---|---|---|
| CPU 使用率 | > 80% 持续 5 分钟 | 识别是哪个进程导致,建议优化方案 |
| 内存使用率 | > 90% | 分析内存泄漏可能性,建议重启策略 |
| 磁盘使用率 | > 85% | 识别大文件/日志,建议清理方案 |
| 系统负载 | > CPU 核心数 | 关联进程分析,建议扩容或限流 |
| 进程状态 | 关键进程不存在 | 自动尝试重启,分析崩溃日志 |
11. 节点配对与连接管理
11.1 节点配对流程
节点使用设备配对(Device Pairing)机制连接到 Gateway:
操作者 Gateway Node Host 操作者 Gateway Node Host #mermaid-svg-jRkpyVxJUXsZSrZp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jRkpyVxJUXsZSrZp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jRkpyVxJUXsZSrZp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jRkpyVxJUXsZSrZp .error-icon{fill:#552222;}#mermaid-svg-jRkpyVxJUXsZSrZp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jRkpyVxJUXsZSrZp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jRkpyVxJUXsZSrZp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jRkpyVxJUXsZSrZp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jRkpyVxJUXsZSrZp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jRkpyVxJUXsZSrZp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jRkpyVxJUXsZSrZp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jRkpyVxJUXsZSrZp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jRkpyVxJUXsZSrZp .marker.cross{stroke:#333333;}#mermaid-svg-jRkpyVxJUXsZSrZp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jRkpyVxJUXsZSrZp p{margin:0;}#mermaid-svg-jRkpyVxJUXsZSrZp .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jRkpyVxJUXsZSrZp text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-jRkpyVxJUXsZSrZp .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-jRkpyVxJUXsZSrZp .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-jRkpyVxJUXsZSrZp .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-jRkpyVxJUXsZSrZp .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-jRkpyVxJUXsZSrZp #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-jRkpyVxJUXsZSrZp .sequenceNumber{fill:white;}#mermaid-svg-jRkpyVxJUXsZSrZp #sequencenumber{fill:#333;}#mermaid-svg-jRkpyVxJUXsZSrZp #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-jRkpyVxJUXsZSrZp .messageText{fill:#333;stroke:none;}#mermaid-svg-jRkpyVxJUXsZSrZp .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jRkpyVxJUXsZSrZp .labelText,#mermaid-svg-jRkpyVxJUXsZSrZp .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-jRkpyVxJUXsZSrZp .loopText,#mermaid-svg-jRkpyVxJUXsZSrZp .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-jRkpyVxJUXsZSrZp .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-jRkpyVxJUXsZSrZp .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-jRkpyVxJUXsZSrZp .noteText,#mermaid-svg-jRkpyVxJUXsZSrZp .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-jRkpyVxJUXsZSrZp .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jRkpyVxJUXsZSrZp .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jRkpyVxJUXsZSrZp .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jRkpyVxJUXsZSrZp .actorPopupMenu{position:absolute;}#mermaid-svg-jRkpyVxJUXsZSrZp .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-jRkpyVxJUXsZSrZp .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jRkpyVxJUXsZSrZp .actor-man circle,#mermaid-svg-jRkpyVxJUXsZSrZp line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-jRkpyVxJUXsZSrZp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 查看待审批请求 节点已配对,可执行命令 WebSocket connect (role: node) 创建配对请求 返回 requestId openclaw devices list 显示待审批节点 openclaw devices approve <requestId> 创建配对记录 配对成功,授予权限
11.2 节点管理 CLI
bash
# 查看所有节点状态
openclaw nodes status
# 查看特定节点详情
openclaw nodes describe --node prod-server
# 查看待审批的配对请求
openclaw devices list
# 批准配对请求
openclaw devices approve <requestId>
# 拒绝配对请求
openclaw devices reject <requestId>
# 移除已配对节点
openclaw nodes remove --node old-server
# 重命名节点
openclaw nodes rename --node node-abc123 --name "prod-server"
11.3 配对权限范围
节点的审批范围取决于其声明的命令表面:
| 节点声明命令 | 授予权限 | 说明 |
|---|---|---|
| 无命令 | operator.pairing |
仅配对,无执行权限 |
| 非执行命令(camera/device 等) | operator.pairing + operator.write |
可读取设备数据 |
system.run / system.which |
operator.pairing + operator.admin |
可执行远程命令 |
⚠️ 安全提示 :包含
system.run的节点配对会授予 admin 权限,请仅对受信任的设备批准此类配对请求。
12. 高级系统操作
12.1 命令管道与组合
在 Shell 命令中,管道(pipe)是组合多个命令的强大机制。OpenClaw 的 exec 工具完整支持管道操作:
json
{
"tool": "exec",
"params": {
"command": "ps aux | grep python | awk '{print $2, $3, $11}' | sort -k2 -rn | head -n 10",
"host": "node",
"node": "prod-server",
"timeout": 15
}
}
这个管道命令组合了四个操作:ps aux 列出所有进程,grep python 过滤 Python 进程,awk 提取 PID、CPU%和命令名,sort 按 CPU 使用率降序排列,head 取前 10 个。这种组合能力让单次 exec 调用就能完成复杂的数据处理。
12.2 脚本文件执行
对于复杂操作,可以编写脚本文件并通过 exec 执行:
json
// 先创建脚本文件
{
"tool": "write",
"params": {
"path": "/tmp/health_check.sh",
"content": "#!/bin/bash\n\nSERVICES=(nginx postgres redis myapp)\nFAILED=()\n\nfor svc in \"${SERVICES[@]}\"; do\n if systemctl is-active --quiet \"$svc\"; then\n echo \"✅ $svc: RUNNING\"\n else\n echo \"❌ $svc: STOPPED\"\n FAILED+=(\"$svc\")\n fi\ndone\n\nif [ ${#FAILED[@]} -gt 0 ]; then\n echo \"\\n⚠️ Failed services: ${FAILED[*]}\"\n exit 1\nelse\n echo \"\\n✅ All services healthy\"\n exit 0\nfi"
}
}
// 然后执行脚本
{
"tool": "exec",
"params": {
"command": "bash /tmp/health_check.sh",
"host": "node",
"node": "prod-server",
"timeout": 30
}
}
这个健康检查脚本遍历一组关键服务,使用 systemctl is-active --quiet 检查每个服务是否运行,输出状态报告,并在有服务停止时返回非零退出码。先通过 write 工具创建脚本文件,再通过 exec 执行,这种模式适合任何需要多步逻辑的运维操作。
12.3 定时监控与 cron 替代
OpenClaw 的 cron 调度能力可以替代传统的 crontab,实现更智能的定时监控:
json5
// 在 openclaw.json 中配置定时任务
{
cron: {
"system-monitor": {
schedule: "*/5 * * * *", // 每5分钟
task: "检查 prod-server 系统状态,如果 CPU>80% 或 内存>90% 则发送告警",
channel: "telegram"
}
}
}
OpenClaw cron vs 系统 crontab:
| 特性 | 系统 crontab | OpenClaw cron |
|---|---|---|
| 配置方式 | 编辑文件 | JSON 配置 / CLI |
| 错误处理 | 邮件通知 | 智能分析 + 多渠道告警 |
| 条件执行 | 需脚本实现 | AI 自然语言描述 |
| 审计追踪 | 需额外配置 | 内置记录 |
| 动态调整 | 需重新编辑 | 运行时修改 |
13. 完整参数参考
13.1 exec 工具参数一览
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
command |
string | ✅ | - | Shell 命令 |
workdir |
string | ❌ | cwd | 工作目录 |
env |
object | ❌ | 继承环境 | 环境变量覆盖 |
host |
enum | ❌ | auto |
执行目标:auto/sandbox/gateway/node |
node |
string | ❌ | - | 节点 ID/名称(host=node 时) |
timeout |
number | ❌ | 配置值 | 超时秒数,0=无限 |
yieldMs |
number | ❌ | 10000 | 延迟后台化毫秒数 |
background |
boolean | ❌ | false | 立即后台执行 |
pty |
boolean | ❌ | false | PTY 模式 |
elevated |
boolean | ❌ | false | 逃逸沙箱 |
security |
enum | ❌ | 配置值 | 安全模式:deny/allowlist/full |
ask |
enum | ❌ | 配置值 | 审批模式:off/on-miss/always |
13.2 常用命令模式速查
| 场景 | 命令模式 | 关键参数 |
|---|---|---|
| 查看文件 | cat /path/file |
timeout=10 |
| 搜索文本 | grep -rn "pattern" /path |
timeout=30 |
| 进程查看 | `ps aux | grep name` |
| 服务管理 | systemctl status/restart svc |
elevated=true |
| 磁盘检查 | df -h |
timeout=10 |
| 网络检查 | curl -sf http://host:port/path |
timeout=15 |
| 日志查看 | tail -n 100 /var/log/file |
timeout=10 |
| Git 操作 | git pull origin main |
workdir=/repo |
| 构建项目 | npm run build |
timeout=300, yieldMs=15000 |
| 长任务 | python3 train.py |
background=true |
14. 最佳实践与常见问题
14.1 最佳实践清单
| # | 实践 | 说明 |
|---|---|---|
| 1 | 🔒 最小权限原则 | 使用 allowlist 模式,仅开放必要命令 |
| 2 | ⏰ 始终设置超时 | 防止命令无限挂起,消耗资源 |
| 3 | 📝 记录关键操作 | 对服务重启、部署等操作保留审计记录 |
| 4 | 🧪 先验证后执行 | 重启服务前先检查配置语法 |
| 5 | 🔄 渐进式部署 | 先在一个节点测试,再批量推广 |
| 6 | 🛡️ 敏感信息保护 | 不在命令中直接传递密码,使用环境变量 |
| 7 | 📊 输出控制 | 对大输出使用 tail/grep/awk 等过滤 |
| 8 | 🔗 使用管道组合 | 单次 exec 完成多步操作,减少调用次数 |
14.2 常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 命令超时 | 执行时间超过 timeout | 增大 timeout 或使用 background |
| 权限不足 | 非 root 用户执行系统命令 | 使用 elevated=true 或 sudo |
| 节点未找到 | 节点未配对或已断开 | openclaw nodes status 检查 |
| 审批被拒绝 | 安全策略不允许该命令 | 检查 allowlist 或调整 security 模式 |
| 输出截断 | 命令输出过大 | 使用 tail/grep 过滤或重定向到文件 |
| Shell 不兼容 | fish 等非 POSIX Shell | OpenClaw 自动回退到 bash/sh |
| 环境变量缺失 | 继承环境不包含所需变量 | 使用 env 参数显式设置 |
| PTY 不可用 | 交互式命令未启用 PTY | 设置 pty=true |
15. 架构全景图
#mermaid-svg-P6bgiRPHvkCJjJyG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-P6bgiRPHvkCJjJyG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-P6bgiRPHvkCJjJyG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-P6bgiRPHvkCJjJyG .error-icon{fill:#552222;}#mermaid-svg-P6bgiRPHvkCJjJyG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-P6bgiRPHvkCJjJyG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-P6bgiRPHvkCJjJyG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-P6bgiRPHvkCJjJyG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-P6bgiRPHvkCJjJyG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-P6bgiRPHvkCJjJyG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-P6bgiRPHvkCJjJyG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-P6bgiRPHvkCJjJyG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-P6bgiRPHvkCJjJyG .marker.cross{stroke:#333333;}#mermaid-svg-P6bgiRPHvkCJjJyG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-P6bgiRPHvkCJjJyG p{margin:0;}#mermaid-svg-P6bgiRPHvkCJjJyG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-P6bgiRPHvkCJjJyG .cluster-label text{fill:#333;}#mermaid-svg-P6bgiRPHvkCJjJyG .cluster-label span{color:#333;}#mermaid-svg-P6bgiRPHvkCJjJyG .cluster-label span p{background-color:transparent;}#mermaid-svg-P6bgiRPHvkCJjJyG .label text,#mermaid-svg-P6bgiRPHvkCJjJyG span{fill:#333;color:#333;}#mermaid-svg-P6bgiRPHvkCJjJyG .node rect,#mermaid-svg-P6bgiRPHvkCJjJyG .node circle,#mermaid-svg-P6bgiRPHvkCJjJyG .node ellipse,#mermaid-svg-P6bgiRPHvkCJjJyG .node polygon,#mermaid-svg-P6bgiRPHvkCJjJyG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-P6bgiRPHvkCJjJyG .rough-node .label text,#mermaid-svg-P6bgiRPHvkCJjJyG .node .label text,#mermaid-svg-P6bgiRPHvkCJjJyG .image-shape .label,#mermaid-svg-P6bgiRPHvkCJjJyG .icon-shape .label{text-anchor:middle;}#mermaid-svg-P6bgiRPHvkCJjJyG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-P6bgiRPHvkCJjJyG .rough-node .label,#mermaid-svg-P6bgiRPHvkCJjJyG .node .label,#mermaid-svg-P6bgiRPHvkCJjJyG .image-shape .label,#mermaid-svg-P6bgiRPHvkCJjJyG .icon-shape .label{text-align:center;}#mermaid-svg-P6bgiRPHvkCJjJyG .node.clickable{cursor:pointer;}#mermaid-svg-P6bgiRPHvkCJjJyG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-P6bgiRPHvkCJjJyG .arrowheadPath{fill:#333333;}#mermaid-svg-P6bgiRPHvkCJjJyG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-P6bgiRPHvkCJjJyG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-P6bgiRPHvkCJjJyG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-P6bgiRPHvkCJjJyG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-P6bgiRPHvkCJjJyG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-P6bgiRPHvkCJjJyG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-P6bgiRPHvkCJjJyG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-P6bgiRPHvkCJjJyG .cluster text{fill:#333;}#mermaid-svg-P6bgiRPHvkCJjJyG .cluster span{color:#333;}#mermaid-svg-P6bgiRPHvkCJjJyG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-P6bgiRPHvkCJjJyG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-P6bgiRPHvkCJjJyG rect.text{fill:none;stroke-width:0;}#mermaid-svg-P6bgiRPHvkCJjJyG .icon-shape,#mermaid-svg-P6bgiRPHvkCJjJyG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-P6bgiRPHvkCJjJyG .icon-shape p,#mermaid-svg-P6bgiRPHvkCJjJyG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-P6bgiRPHvkCJjJyG .icon-shape .label rect,#mermaid-svg-P6bgiRPHvkCJjJyG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-P6bgiRPHvkCJjJyG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-P6bgiRPHvkCJjJyG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-P6bgiRPHvkCJjJyG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输出层
执行层
Gateway 层
AI Agent 层
🤖 Agent 会话
📋 exec 调用
📊 process 管理
🔐 安全审查
🔀 路由决策
📝 审批管理
⏱️ 超时控制
📦 Sandbox
🖥️ Gateway Host
📱 Node Host A
📱 Node Host B
📤 stdout 捕获
📤 stderr 捕获
🔢 退出码
16. 总结与展望
16.1 核心要点回顾
本文全面解析了 OpenClaw 的命令执行体系,核心要点如下:
| 主题 | 关键要点 |
|---|---|
| exec 基础 | command 必填,host 决定执行目标,node 指定远程节点 |
| 执行模式 | 同步(默认)、yieldMs(延迟后台)、background(立即后台) |
| 安全机制 | deny/allowlist/auto/ask/full 五级安全,审批机制保障合规 |
| 超时控制 | timeout 参数覆盖所有执行模式,0=无限需慎用 |
| 输出捕获 | 完整捕获 stdout/stderr,大输出需过滤或重定向 |
| 节点执行 | host=node + node 参数,通过 WebSocket 转发 system.run |
| 环境配置 | workdir 指定目录,env 覆盖变量,pty 支持 TTY |
16.2 与传统方案对比
| 维度 | SSH + Shell | Ansible | OpenClaw exec |
|---|---|---|---|
| 交互方式 | 手动终端 | YAML Playbook | AI 自然语言 |
| 学习成本 | 低 | 中 | 低(AI 理解意图) |
| 安全控制 | 系统权限 | 模块限制 | 五级安全 + 审批 |
| 智能分析 | 无 | 无 | AI 分析输出 |
| 多渠道 | 无 | 无 | 聊天/飞书/Telegram 等 |
| 扩展性 | 脚本 | 插件 | Skills 生态 |