Hermes + PinchTab 浏览器引擎手册 🦎

🦎 Hermes + PinchTab 浏览器引擎手册

版本: 4.0 | 更新日期: 2026-06-09 | 维护人: Hermes Agent


📑 目录

  1. 部署
    • 1.1 安装(在 Hermes 对话中完成)
    • 1.2 存在形式与依赖
    • 1.3 卸载
    • 1.4 运行时架构字符图
  2. 使用
    • 2.1 触发(如何在 Hermes 对话中调用)
    • 2.2 Agent 实际行为
    • 2.3 PinchTab 行为
  3. 配置
    • 3.1 PinchTab 完整配置
    • 3.2 MCP 集成配置
    • 3.3 安全策略
    • 3.4 网络拦截
  4. Hermes 浏览性能对比
  5. 故障排查清单

1. 🚀 部署

1.1 安装(在 Hermes 对话中完成)

用户只需在 Hermes 对话中输入一条消息,Agent 即自动完成全部安装:

安装 pinchtab 到默认路径,注册 MCP,放行所有域名,禁用原生浏览器,使用已有的 Chromium 引擎

这条消息覆盖以下要点:

Agent 收到对话后的实际执行步骤

# ── Step 1: 安装 pinchtab ─────────────────────────────────────
cd /opt/data/home
npm init -y
npm install pinchtab

# 或从 GitHub Releases 下载独立二进制(当前环境使用)
# 路径: /opt/data/mcp/pinchtab/pinchtab (v0.13.0)
# 来源: GitHub releases → pinchtab-linux-amd64

# ── Step 2: 配置安全策略 + 浏览器引擎 ────────────────────────
pinchtab config set security.allowedDomains '["*"]'
pinchtab config set browser.binary \
  /opt/data/home/.local/share/playwright/chromium-1217/chrome-linux64/chrome

# ── Step 3: 注册 MCP + 禁用原生浏览器 ────────────────────────
# 修改 config.yaml:
#   mcp_servers:
#     pinchtab:
#       command: /opt/data/home/pinchtab/node_modules/.bin/pinchtab
#       args: ["mcp"]                    # ← 官方推荐,无 --server
#       timeout: 120
#   disabled_toolsets: [browser, web]

# ── Step 4: CLI 验证 ──────────────────────────────────────────
pinchtab nav https://example.com --json
# 返回 { url, title, tabId } 即代表浏览器引擎可用

# ── Step 5: 重启 Gateway ──────────────────────────────────────
fuser -k 9867/tcp 2>/dev/null
systemctl --user restart hermes-gateway

# ── Step 6: 最终验证 ──────────────────────────────────────────
# 确认 mcp_pinchtab_navigate 工具可用

红线速查

红线正确做法错误后果
安装路径$HOME/pinchtab/(volume 内)换环境文件丢失
安全策略pinchtab config set ...(CLI 持久化)无法访问外部网站
MCP 参数args: ["mcp"],无额外参数stdout 污染,MCP 断开
运行模式MCP stdio 直调,不用 server daemon实例卡在 stopping
浏览器引擎复用已有的 Playwright Chromium多下载 279MB

安装验证清单

#检查项通过标准
1pinchtab --version0.12.0+
2pinchtab nav https://example.com --json返回页面 title/url
3Gateway 重启成功无异常日志
4MCP 工具可用"打开 example.com" 正常执行
5无需手动创建 config.json自动生成
6无需 security downconfig set 持久化
7无需手动管理进程Hermes MCP 自动管理

1.2 存在形式与依赖

PinchTab 在 Hermes 环境中的存在形式

PinchTab 是一个 MCP 服务器工具,以 Hermes MCP 插件形式运行。它不是一个常驻服务进程,而是由 Hermes Gateway 通过 stdio 按需启动/管理的子进程。

组件路径/形式说明
PinchTab 二进制/opt/data/mcp/pinchtab/pinchtab
$HOME/pinchtab/node_modules/.bin/pinchtab
Go 静态编译单文件,版本 v0.13.0
配置目录/opt/data/home/.pinchtab/server 配置、日志、PID
MCP 配置/opt/data/.pinchtab/config.jsonMCP 工具读取的配置(token 同步用)
Hermes MCP 配置~/.hermes/config.yaml 中 mcp_servers 段注册 MCP 工具
Profile 目录/opt/data/home/.pinchtab/profiles/default浏览器用户数据
Extensions/opt/data/home/.pinchtab/extensions浏览器扩展

依赖项

依赖版本路径说明
Chromium144.0.7559.133/opt/data/home/.local/share/playwright/chromium-1217/chrome-linux64/chrome复用 Playwright 捆绑版,headless 运行;如无 Playwright 则自动下载
Node.js(仅 npm 安装需)npm install 时需 Node.js;独立二进制版无需
Go 运行时无需,PinchTab 是 Go 静态编译二进制
沙箱能力容器环境需 --no-sandbox,已自动处理

磁盘占用

PinchTab 二进制:  19MB  (Go 单文件)
Chromium 引擎:   279MB  (Playwright 捆绑版)
npm 包:          ~50MB
合计:           ~348MB

1.3 卸载

# ── 方式 A: npm 安装版 ─────────────────────────────────────
cd /opt/data/home/pinchtab
# 删除 npm 包
npm uninstall pinchtab

# ── 方式 B: 独立二进制版 ────────────────────────────────────
rm /opt/data/mcp/pinchtab/pinchtab

# ── 清理配置和数据 ──────────────────────────────────────────
rm -rf /opt/data/home/.pinchtab
rm -rf /opt/data/.pinchtab

# ── 恢复 Hermes MCP 配置 ────────────────────────────────────
# 编辑 ~/.hermes/config.yaml:
#   删除 mcp_servers.pinchtab 段
#   删除 disabled_toolsets 中的 browser,web(如需恢复)

# ── 重启 Gateway ────────────────────────────────────────────
fuser -k 9867/tcp 2>/dev/null
systemctl --user restart hermes-gateway

1.4 运行时架构字符图

┌──────────────────────────────────────────────────────────────┐
│                  PinchTab 运行时架构 (v0.13.0)               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Hermes Agent (MCP Client)                                  │
│      │  JSON-RPC over stdio                                  │
│      ▼                                                       │
│  ┌───────────────────────────────────────┐                   │
│  │  pinchtab mcp  (PID 5906)             │                   │
│  │  MCP Bridge - 管理实例生命周期        │                   │
│  │  · 监听 Hermes MCP 调用              │                   │
│  │  · 启动/停止 Chrome 实例             │                   │
│  │  · 转发 JSON-RPC 请求为 HTTP API     │                   │
│  └──────────────┬────────────────────────┘                   │
│                 │ HTTP (localhost:9867)                        │
│                 ▼                                              │
│  ┌───────────────────────────────────────┐                   │
│  │  pinchtab server  (PID 6033)          │                   │
│  │  端口 9867 - 中央控制面               │                   │
│  │  · HTTP API 入口 (health/nav/snap)    │                   │
│  │  · Token 鉴权                         │                   │
│  │  · 实例路由                           │                   │
│  └──────────────┬────────────────────────┘                   │
│                 │                                              │
│                 ▼                                              │
│  ┌───────────────────────────────────────┐                   │
│  │  pinchtab bridge  (PID 6042)          │                   │
│  │  端口 9868 - 实例代理                 │                   │
│  │  · 转发 CDP 命令到 Chrome             │                   │
│  │  · 管理标签页状态                     │                   │
│  └──────────────┬────────────────────────┘                   │
│                 │ CDP (Chrome DevTools Protocol)              │
│                 ▼                                              │
│  ┌───────────────────────────────────────┐                   │
│  │  Chrome  (PID 6055)                   │                   │
│  │  headless=new 模式                    │                   │
│  │  CDP 端口 9869                        │                   │
│  │  Profile: /tmp/pinchtab-xxx           │                   │
│  ├───────────────────────────────────────┤                   │
│  │  ├── chrome zygote (PID 6061)         │                   │
│  │  ├── chrome utility: network          │                   │
│  │  ├── chrome utility: storage          │                   │
│  │  └── chrome renderer (PID 6155+)      │                   │
│  └───────────────────────────────────────┘                   │
│                                                              │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│                    端口分配                                    │
├──────────────┬─────────────────┬─────────────────────────────┤
│   9867       │ Server          │ 中央控制面 (health, nav)    │
│   9868       │ Bridge          │ 实例代理 (CDP 转发)         │
│   9869       │ Chrome CDP      │ 远程调试端口                │
│   9888       │ Profile Server  │ 用户数据同步 (通常不跑)     │
└──────────────┴─────────────────┴─────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│                    Token 鉴权链路                              │
├──────────────────────────────────────────────────────────────┤
│  1. Server 启动时生成 token (或从 config 读取)               │
│  2. token 写入 /opt/data/home/.pinchtab/server.pid          │
│  3. token 也写入 /opt/data/.pinchtab/config.json (需同步)   │
│  4. MCP 工具从 /opt/data/.pinchtab/config.json 读取 token   │
│  5. 所有 HTTP 请求携带 Authorization: Bearer <token>       │
│  6. Server 验证 token → bridge → Chrome                    │
└──────────────────────────────────────────────────────────────┘
⚠️ 关键坑点:两个 config.json 中的 token 必须手动同步!

2. 🛠️ 使用

2.1 触发(如何在 Hermes 对话中调用 PinchTab 执行任务)

用户无需直接操作 PinchTab。Hermes Agent 在收到与浏览器操作相关的需求时,会自动调用 PinchTab MCP 工具完成。

用户触发方式

只需在对话中提出浏览器操作需求,例如:

  • 打开 example.com
  • 帮我搜一下 xxx 的图片
  • 去这个网址看看有什么内容
  • 截个图给我
  • 点击那个搜索按钮

触发流程

用户发消息 → Hermes Agent 识别需求
           → Agent 判断需要浏览器操作
           → Agent 调用 mcp_pinchtab_* 工具
           → PinchTab MCP 执行操作
           → 结果返回 Agent
           → Agent 汇总结果回复用户

2.2 Agent 实际行为

当 Agent 需要使用浏览器时,其行为模式如下:

导航类任务

Agent 行为:
1. 调用 mcp_pinchtab_navigate(url=目标URL)
2. 等待加载完成
3. 调用 mcp_pinchtab_get_text() 获取页面文本
4. 分析内容并回复用户

# 可选增强:
4a. 调用 mcp_pinchtab_snapshot(compact=true) 获取页面结构
4b. 根据结构决定下一步交互

搜索类任务

Agent 行为:
1. 调用 mcp_pinchtab_navigate(url=搜索引擎+关键词)
2. 等待搜索结果加载
3. 调用 mcp_pinchtab_snapshot() 获取结果列表
4. 遍历结果链接,选择性访问
5. 汇总信息回复用户

交互类任务

Agent 行为:
1. 导航到目标页面
2. 调用 mcp_pinchtab_snapshot() 了解页面结构
3. 通过 mcp_pinchtab_find(query="搜索框") 定位元素
4. 调用 mcp_pinchtab_fill(selector, value) 填写内容
5. 调用 mcp_pinchtab_click(selector) 点击按钮
6. 等待结果并获取反馈

截图/导出类任务

Agent 行为:
1. 导航到目标页面
2. 调用 mcp_pinchtab_screenshot() 截图
3. 图片通过 MEDIA: 路径直接发送给用户

# PDF 导出:
2b. 调用 mcp_pinchtab_pdf()
3b. 输出为 base64 PDF

2.3 PinchTab 行为

进程生命周期

1. Hermes 启动时加载 MCP 配置
2. Agent 首次调用 PinchTab 工具时:
   - Hermes Gateway 通过 stdio 启动 `pinchtab mcp`
   - PinchTab 自动启动 server + bridge + Chrome(进程链)
   - 初始化约 3-5 秒(首次调用可能有 503 瞬态)
3. 后续调用复用已有进程,无需重新初始化
4. 空闲超时后自动回收资源

MCP 工具清单(共约 38 个)

分类工具说明
导航pinchtab_navigate导航到 URL(可选 snap 参数)
pinchtab_go_back / forward前进/后退
pinchtab_reload刷新页面
交互pinchtab_click点击元素(支持 ref/CSS/XPath/text 定位)
pinchtab_fill填写输入框
pinchtab_type键盘输入
pinchtab_select下拉框选择
内容pinchtab_snapshot获取 aria 可访问性树(支持 compact/text 格式)
pinchtab_get_text提取页面纯文本
截图pinchtab_screenshot页面截图(支持元素级裁剪、注解框标注)
标签管理pinchtab_list_tabs列出所有标签页
pinchtab_close_tab关闭指定标签页
等待pinchtab_wait_for_load等待页面加载完成
pinchtab_wait_for_selector等待元素出现/消失
pinchtab_wait_for_text等待文本出现
pinchtab_wait_for_url等待 URL 变更
网络pinchtab_network查看捕获的网络请求
pinchtab_network_route / unroute请求拦截/放行
其他pinchtab_cookiesCookie 管理
pinchtab_dialog处理 alert/confirm/prompt
pinchtab_eval执行 JavaScript
pinchtab_pdf导出 PDF

PinchTab 内部行为

  • 初始化:首次调用时启动完整的进程链(mcp → server → bridge → Chrome),耗时约 3-5 秒
  • 导航:通过 CDP 协议控制 Chrome,复用已有实例,后续导航仅 ~224ms
  • 快照:通过 aria 可访问性树提取页面结构,附带元素 ref 定位信息(e1, e2, ...)
  • 交互:通过 CDP 协议直接操作页面 DOM,支持多种元素选择策略
  • 资源回收:空闲超时后自动关闭 Chrome 实例以节省内存
  • 错误处理:导航失败自动重试;CDP 断开自动重建连接

3. ⚙️ 配置

3.1 PinchTab 完整配置

配置来源:/opt/data/home/.pinchtab/config.json(首次运行自动生成)。所有修改通过 CLI 命令持久化。

Server 配置

server.port9867监听端口
server.bind127.0.0.1绑定地址(保持 loopback)
server.token自动生成API 认证 token
server.stateDir/opt/data/home/.pinchtab状态目录

安全配置

security.allowedDomains["*"]放行所有域名(默认仅 localhost)
security.idpi.enabledtrue内容检测
security.idpi.strictModetrue严格模式
信任 CIDR192.168.x.x, 10.x.x.x, 172.16.x.x内网信任

浏览器配置

browser.binary/opt/data/home/.local/share/playwright/chromium-1217/chrome-linux64/chrome
运行模式headless=new
窗口尺寸1280×800(虚拟),800×600(ozone-override)
语言en-US
User-AgentMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.7559.133 Safari/537.36
沙箱--no-sandbox(容器必需)

Multi-Instance(多实例)

strategyalways-on实例策略
allocationPolicyfcfs先到先得
端口范围9868–9968实例端口池
重启策略max 20次, 初始退避 2s, 最大 60s实例崩溃自动重启

超时配置

actionSec30s交互超时
navigateSec60s导航超时
shutdownSec10s关闭超时
Hermes MCP timeout120sconfig.yaml 中设置

持久化操作命令

pinchtab config set security.allowedDomains '["*"]'     # 放行所有域名
pinchtab config set browser.binary /path/to/chromium    # 指定浏览器
pinchtab config set server.port 9868                    # 换端口
pinchtab config list                                     # 查看配置
pinchtab config export > backup.json                     # 导出配置

3.2 MCP 集成配置

Hermes config.yaml 配置段

mcp_servers:
  pinchtab:
    command: /opt/data/mcp/pinchtab/pinchtab
    # 或: /opt/data/home/pinchtab/node_modules/.bin/pinchtab
    args: ["mcp"]                 # ← 只能写 mcp,不加 --server
    timeout: 120

disabled_toolsets: [browser, web] # 禁用原生浏览器工具集

参数红线:args 只能写 ["mcp"],加 --server 会污染 stdout(输出非 JSON 行),导致 MCP 连接断开。

3.3 安全策略

域名白名单

# ✅ 持久化修改(推荐)
pinchtab config set security.allowedDomains '["*"]'

# ❌ 不要用 security down(重启后失效)
# ❌ 不要手动编辑 config.json(用 CLI)

内网信任

trustedProxyCIDRs: ["192.168.1.120/32"]
trustedResolveCIDRs: ["192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12"]

敏感 API 默认禁用(按需开启)

allowEvaluate: false       # JavaScript 执行
allowMacro: false          # 宏
allowScreencast: false     # 屏幕录制
allowDownload: false       # 文件下载
allowCookies: false        # Cookie 操作
allowNetworkIntercept: false  # 网络拦截
allowUpload: false         # 文件上传
allowClipboard: false      # 剪贴板
allowStateExport: false    # 状态导出

3.4 网络拦截

PinchTab 支持请求拦截(network_route),分为三种模式:

模式操作说明
阻止action=abort阻止匹配请求
模拟action=fulfill返回模拟响应(安全域名被禁)
放行action=continue通过请求

安全限制:fulfill 在 security.allowedDomains 列表中的域名被阻止(防止绕过安全策略对被授权站点进行中间人攻击),仅允许在非白名单域名上使用。


4. 📊 Hermes 浏览性能对比

测试日期:2026-05-18 | 环境:Hermes Agent v2026.5.16, aarch64 Linux (Docker), 4-Core, 22GB RAM

Chromium:Playwright 捆绑版 headless_shell (Chrome 144) — 三引擎复用同一二进制

方法:每个 URL 连续测试 3 次(warm),取均值;等待策略 DOMContentLoaded;跳过冷启动首次

4.1 导航性能(毫秒,越低越好)

引擎 Simple
example.com
Medium
httpbin/html
Complex
Wikipedia
平均 相对
🏆 Pinchtab 0.12.0
Go + Chrome CDP
224ms 528ms 560ms 437ms 1.0x
Playwright 1.59.0
Python + Chrome CDP
517ms 1,477ms 1,307ms 1,100ms 2.5x
Agent-Browser 0.27.0
Node.js + Hermes Native
999ms 1,293ms 1,617ms 1,303ms 3.0x

4.2 冷启动性能

引擎 冷启动(首次导航) 说明
Pinchtab 961ms Go server 启动 + Chrome CDP 连接 + 导航;后续导航复用实例仅 ~224ms
Playwright 517ms* *每个测试固有包含了 Python 启动 + 浏览器进程启动,无法避免每次往返
Agent-Browser 1,048ms npx 命中缓存后 Node.js 启动 + Agent-Browser 初始化 + Chrome 启动 + 导航

4.3 内容提取性能

引擎 Snap 耗时 输出量 说明
Pinchtab snap 2,804ms ~49KB DOM 树 aria 可访问性树提取,包含元素 ref 定位信息
Playwright content() 即时 ~617KB(Wikipedia) 全量 HTML,无结构摘要
Agent-Browser N/A N/A 需要 snap 命令,测试时未安装浏览器(ARM64 不兼容)

4.4 资源占用

引擎 二进制/包体积 + Chromium 进程模型 说明
Pinchtab 19MB (Go 单文件) 279MB 常驻 daemon Go 静态编译,零依赖;二进制最小
Playwright 133MB (Python) 279MB 每次启动新进程 Python 含完整浏览器驱动
Agent-Browser 162MB (npm + Node.js) 279MB 每次启动新进程 需要 Node.js 运行时;npx 缓存需另计

4.5 分析

为什么 Pinchtab 快这么多?

  1. Go 静态编译 — 单二进制,无解释器/VM 开销,启动即毫秒级
  2. 常驻 daemon 架构 — Server + Bridge + Chrome 持续运行,后续导航只需 HTTP API 调用(~224ms),非每次重新启动整个浏览器
  3. 简洁的 MCP 桥接 — MCP stdio → Bridge HTTP → Chrome CDP,链路最短

Playwright 的优劣

  • 优:Python API 功能最全,内容提取(content()/text())无需额外调用
  • 劣:每次调用的 Python 进程启动 + 浏览器 launch 开销约 300-500ms,即使只是简单导航
  • 劣:variance 大(如 medium 页面 983-1989ms),受 Python GC 影响

Agent-Browser(Hermes 原生)的优劣

  • 劣:Node.js 启动 + npx 解析 + Agent-Browser JS 初始化,三项叠加约 500ms 固定开销
  • 劣:v2026.5.16 在 ARM64 上无法自动下载 Chrome(Chrome for Testing 不提供 ARM64 构建),需手动 --executable-path
  • 优:内容提取使用 aria 可访问性树(带元素 ref),比完整 HTML 更友好
  • 优:variance 最小 — 所有 URL 的导航时间接近(999ms vs 864ms),说明瓶颈在初始化层而非网络

4.6 结论

Pinchtab 在导航性能上是 Playwright 的 2.5 倍、Agent-Browser 的 3 倍。

如果你的 Hermes Agent 需要频繁进行浏览器操作(导航、点击、数据提取),推荐使用 Pinchtab 作为 MCP 浏览器引擎,禁用原生 browser 工具集,并在 MCP 中配置 Pinchtab。

Playwright 适合需要完整 Python 控制能力的场景;Agent-Browser(原生 browser 工具)适合临时轻量浏览。

5. 🔧 故障排查清单

5.1 401 missing_token / bad_token

症状:所有 API 返回 401

根因:两个 config.json 中 token 不一致(Server 重启后生成了新 token,但 MCP 配置未同步)

解决:

# 对比两个 config 中的 token
cat /opt/data/home/.pinchtab/config.json | grep token
cat /opt/data/.pinchtab/config.json | grep token
# 如不一致,手动同步
cp /opt/data/home/.pinchtab/config.json /opt/data/.pinchtab/config.json
# 或重启 Gateway 重新加载
systemctl --user restart hermes-gateway

5.2 MCP 工具不可用

症状:Agent 中看不到 mcp_pinchtab_* 工具

排查:

# 1. 检查 MCP 配置是否正确
grep -A5 "pinchtab:" ~/.hermes/config.yaml
# 2. 确认 args 只有 ["mcp"]
# 3. 检查 disabled_toolsets 是否误配置
# 4. 重启 Gateway 重新加载 MCP
systemctl --user restart hermes-gateway

5.3 导航失败 / 503 Service Unavailable

症状:导航时返回 503 或页面空白

排查顺序:

  1. 安全策略:pinchtab config get security.allowedDomains — 是否包含目标域名?
  2. Server 是否运行:curl http://127.0.0.1:9867/health — 返回 ok?
  3. 端口冲突:fuser 9867/tcp — 是不是旧进程占着?
  4. Chrome 二进制:pinchtab config get browser.binary — 路径是否存在?
  5. 初始化延迟:首次调用有 3-5 秒初始化窗口,重试即可

5.4 MCP 快照失败

症状:snapshot 返回空或错误

排查:

# 1. 先确认导航成功
pinchtab nav https://example.com --json
# 2. 检查 bridge (9868) 是否在监听
ss -tlnp | grep 9868
# 3. 检查 Chrome CDP 端口 (9869)
ss -tlnp | grep 9869

5.5 MCP Connection closed / stdout 污染

症状:调用工具时报 Connection closed

根因:MCP args 加了 --server,导致 pinchtab mcp 输出 HINT: 非 JSON 行

解决:

# args 只保留 ["mcp"]
args: ["mcp"]   # ✅ 正确
# args: ["mcp", "--server"]   # ❌ 错误

5.6 Chrome 无法启动(沙箱错误)

症状:日志显示 "Failed to move to new namespace" 或沙箱相关错误

解决:容器环境必须 --no-sandbox,已在 config 中配置

5.7 内存占用过高

症状:系统内存不足

分析:每个渲染进程约 100-170MB,多标签页场景注意内存

缓解:

# 查看 Chrome 进程数量
ps aux | grep chrome | wc -l
# 清理未被使用的标签页实例
rm -rf /opt/data/.pinchtab/instances/*
systemctl --user restart hermes-gateway

5.8 常见问题速查表

问题排查方向
MCP 工具不可用检查 Hermes 是否重新加载了 MCP 配置
连接失败确认 pinchtab server 进程在运行
CDP 连接失败检查 Chrome 主进程是否存活,端口 9869 是否监听
域名被拒检查 security.allowedDomains 配置
Token 认证失败两个 config.json 中的 token 必须一致
首次 503初始化延迟 3-5 秒,重试即可
Chrome 沙箱错误容器环境需 --no-sandbox
内存占用过高每个渲染进程约 100-170MB,多标签页注意内存
无系统 Chrome使用 Playwright 捆绑版,不要依赖 /usr/bin/chrome

— 本文档由 Hermes Agent 维护于 Trilium | v4.0 重构结构:部署/使用/配置/性能对比/故障排查