Apache Lens CLI 命令与查询实战详解

基于 Ubuntu 22.04 实测环境详解 Apache Lens 2.2.0-beta 的 CLI 会话操作、help 命令体系、查询提交与结果获取全流程,包含解析报错、驱动路由与子进程排障的真实回显。

Apache LensLensApache运维数据分析2026/10/15

Apache Lens CLI 命令与查询实战详解

一、实战环境与连接方式

本文全部操作在 Ubuntu 22.04 实测完成:Lens 2.2.0-beta 服务端按单机本地模式运行(Hadoop 2.6.0 jar 供类路径、Hive 0.13.3-inm 依赖、内嵌 HiveServer2 + 本地 MapReduce),客户端使用官方 lens-cli.sh,服务端 REST API 地址为 http://localhost:9999/lensapi/。Lens 已于 2020 年 8 月退役、2021 年 4 月进入 Attic,终版即 2.2.0-beta,本文定位为遗产系统运维与学习研究。

CLI 位于发行包 client/bin/lens-cli.sh,直接执行进入交互式终端,实测启动横幅与提示符如下:

=======================================
*                                     *
*            Lens Client              *
*                                     *
=======================================

Welcome to Lens Client
lens-shell>

连接方式是自动的:CLI 不设独立的 connect 命令,首条需要服务端的命令执行时会自动按配置建立服务端会话,实测首条 show databases 直接返回结果,服务端日志同步出现会话建立记录。CLI 与服务端同属一个发行包但可分机部署:发行包 client 目录自带 conf 子目录,修改其中的服务地址配置即可让 CLI 指向远端 LensServer,本地实测时两者同机,会话参数回显中的 lens.server.base.url 即指向 0.0.0.0:9999。批量场景下用管道向 CLI 喂命令序列、以 exit 结束即可,本文所有实测均采用该方式,读者可原样复现。

二、help 命令体系总览

CLI 进程的启动横幅与终端特性值得先记录一笔。发行包 client/bin/lens-cli.sh 启动后进入交互式提示符 lens-shell>,所有命令在该提示符下执行;终端基于 JLine 实现,支持 TAB 补全——这条特性有一处实测佐证:输入未注册命令时回显的 Command '!echo HELLO_FROM_OS' not found (for assistance press TAB) 明确建议按 TAB 查看可用命令,说明补全体系覆盖注册命令及其选项。CLI 自身也有留痕:client 目录下的 lens-cli-hist.log 持续追加历史命令(实测该文件随使用增长),加上 client/logs 目录,客户端侧行为同样可审计。批量执行时把命令序列经管道送入 stdin 即可,每行一条,末行以 exit 收尾,CLI 顺序执行完自动退出,这是自动化巡检脚本的推荐形态。两个与脚本化相关的行为要点:其一,命令间没有事务性,前一条失败不阻断后一条,脚本需自行按回显判断成败;其二,每次管道执行都会新建一个会话(服务端 query_logs 下对应新增一个会话目录),跨脚本的资源注册不会延续。

在 lens-shell 中执行 help 列出全部命令,实测输出按字母序排列,覆盖六大类操作。会话与资源类包括:

* add file - Adds a file resource to session
* add jar - Adds jar resource to the session
* bye - Releases all resources of the server session and exits the shell
* close - Releases all resources of the server session and exits the shell
* get - Fetches and prints session parameter specified with name <key> from lens server
* show params - Fetches and prints all session parameter from lens server

元数据建模类包括 create/drop/describe 对 cube、dimension、dimtable、fact、storage 的完整操作族,以及 show 系列列表命令:

* create cube - Create a new Cube, taking spec from <path-to-cube-spec-file>
* create database - create a database with specified name. if <ignore-if-exists> is true, ...
* describe cube - describe cube with name <cube_name>
* drop fact - drops fact <fact_name>. If <cascade> is true, ...
* show cubes - show list of cubes in current database
* show databases - displays list of all databases
* show nativetables - show list of native tables belonging to current database

查询类命令是运维与使用的主战场:

* query details - Get query details of query with handle <query_handle>
* query execute - Execute query <query-string>. If <async> is true, ...
* query explain - Explain execution plan of query <query-string>. ...
* query kill - Kill query with handle <query_handle>
* query list - Get all queries. Various filter options can be provided(optionally)
* query results - get results of query with query handle <query_handle>. ...
* query status - Fetch status of executed query having query handle <query_handle>

另有几条实用命令,实测行为逐一确认过:date 输出本地时间(回显形如 "Wednesday, October 14, 2026 10:35:07 PM GMT");debug 开关调试日志,切换时无回显但随后 DEBUG 级日志会出现在终端流中,再执行一次即关闭;cls/clear 清屏。需要特别修正一个易被文档误导的点:帮助文本提示的 ! 前缀执行操作系统命令在实测中不可用,输入 !echo 得到的回显是 Command '!echo HELLO_FROM_OS' not found (for assistance press TAB)——该版本 CLI 并未注册系统命令桥接,需要 shell 操作时另开终端执行,不要在脚本里依赖该特性。help 的完整输出配合命令级 --help 可以覆盖日常使用,这是不熟悉 Lens 命令体系时的第一入口。

从命令族的全貌看,help 输出虽按字母序排列,语义上可归为六组:会话与参数组(show params/get/add jar/close/bye)、元数据组(show databases/create database/use database/show cubes/describe 系)、查询执行组(query execute/explain/status/results/details/kill/list)、调度组(scheduler create/list/status/kill,按周期定义定时查询)、配置与运维组(show params、debug、cls)与退出组(exit/quit)。查询执行组是日常主力,元数据组是建模入口,调度组则是 Lens 平台化定位的直接体现——把周期性报表固化为服务端调度任务而不是 crontab 里的裸 SQL。理解六组划分后,help 输出不再是字母表而是能力地图,新命令按组检索即可快速定位;配合命令级 help <命令> 可以看到每个选项的关键字、是否必填与默认值(第六节的 async 选项表即由此而来),两层 help 加 TAB 补全构成完整的自助探索路径。

三、会话操作实测:参数与身份

建立会话后,用 show params 拉取会话参数,实测输出(节选):

lens.query.result.split.multiple=false
lens.query.result.split.multiple.maxrows=100000
lens.server.base.url=http://0.0.0.0:9999/lensapi
lens.server.drivers=org.apache.lens.driver.hive.HiveDriver,org.apache.lens.driver.jdbc.JDBCDriver
lens.session.cluster.user=root
lens.session.loggedin.user=anonymous
silent=off

这份回显信息量很大:lens.server.base.url 确认会话连到本机 9999 端口;lens.server.drivers 显示当前加载的双驱动配置;lens.session.loggedin.user=anonymous 提示默认鉴权为匿名——生产化改造的第一件事就是接入认证并收紧这里。单个参数可用 get <key> 精确拉取。会话期间可用 add jar、add file 向服务端注册资源供查询加载,close 或 bye 释放会话退出终端;实测服务端停止时会话目录被标记 SESSION_CLOSED,会话资源随之释放。

参数清单里有两个身份字段容易被混为一谈,值得拆开讲。lens.session.loggedin.user 是 CLI 侧登录身份,默认部署没有任何认证插件,固定为 anonymous;lens.session.cluster.user 是会话向下传递给 Hadoop 后端的代理用户(默认取执行服务进程的操作系统用户),决定 MapReduce 任务以哪个队列用户身份跑。两者在无认证环境下同为 root 亦不稀奇,但概念上一横一纵:前者回答"谁在用 Lens",后者回答"这个人的任务以谁的身份落在集群上"。接入认证后前者来自认证体系,后者仍需 kerberos 或 doas 机制映射,这是把评估环境推向生产时必须补齐的一条链路。silent 参数(回显中 silent=off)控制 CLI 是否抑制提示性回显,脚本化时置 on 可让输出更干净,交互排障时保持 off 以便看到每条命令的执行轨迹。

数据库命名空间是会话的顶层边界,实测 show databases 返回:

default

Lens 维护自己的数据库列表(与后端 Hive 的库是两层命名体系),建模与查询都在当前 Lens 数据库内进行,配合 create database / use database 可实现多项目隔离。

四、查询提交:从句柄到驱动路由

用 query execute 提交一条最简查询:

lens-shell>query execute select 1+1

实测输出:

14 Oct 2026 21:24:40,926 [Spring Shell] INFO  cliLogger  - Query handle: 1f49eb19-4718-421e-845f-7c098f246220
14 Oct 2026 21:24:45,995 [Spring Shell] INFO  cliLogger  - User query: 'select 1+1' was submitted to org.apache.lens.driver.hive.HiveDriver
14 Oct 2026 21:24:45,995 [Spring Shell] INFO  cliLogger  -  Driver query: 'INSERT OVERWRITE DIRECTORY "file:/tmp/lensreports/hdfsout/1f49eb19-4718-421e-845f-7c098f246220"  select 1+1 ' and Driver handle: OperationHandle [opType=EXECUTE_STATEMENT, getHandleIdentifier()=3b8cdd71-2991-4022-999c-4ef821b4882a]
_c0
Results of query stored at : file:/tmp/lensreports/hdfsout/1f49eb19-4718-421e-845f-7c098f246220 -1 rows process in (5) seconds.

这段真实回显完整呈现了 Lens 的执行流水线:提交即分配查询句柄(形如 1f49eb19 开头的 UUID);服务端解析后路由到 HiveDriver(日志写明 submitted to org.apache.lens.driver.hive.HiveDriver);驱动侧语句被统一改写为 INSERT OVERWRITE DIRECTORY 形式,结果按句柄落盘到 /tmp/lensreports/hdfsout/<句柄>;CLI 随后回显结果列名 _c0 与落盘路径、耗时。结果文件内容为:

2

即 1+1 的求值结果。值得说明的是流程中的选择逻辑:双驱动并存时服务端对每个候选驱动做代价估计,估计失败的驱动退出候选——实测 JDBC 驱动在估计阶段抛空指针被淘汰,查询由 HiveDriver 承接;同时查询被 Hive 语法解析把关,任何不合语法的输入都进不了路由阶段,下节的报错回显正是这一机制的真实记录。

落盘文件的组织也值得看一眼:结果目录下实际文件名为 000000_0(Hive 输出格式的惯例命名),纯文本、每行一条结果记录,下游程序可直接消费。异步提交的正确写法是把开关写成 Spring Shell 选项形式 --async true,实测 query execute --async true select 1+2 立即返回裸句柄(形如 7f2f6529-5565-4f80-8adc-f81b896c3d60,不带 Query handle 前缀),客户端无需等待执行完成;一个真实的反例是把开关词写进查询正文——query execute async true select 1+2 会把 "async true select 1+2" 整体当作 SQL 提交,服务端照样先做 Hive 解析,返回错误码 3001,报错定位指向 'async' 关键字。这个反例说明 CLI 参数与查询正文的边界完全靠选项语法区分,写脚本时务必核对 help query execute 的选项表。

query explain 的实测输出值得单独解读,它揭示了两层机制。输出先是完整的 Hive 抽象语法树(ABSTRACT SYNTAX TREE 段落,TOK_QUERY/TOK_INSERT 层级展开),随后是 STAGE DEPENDENCIES 与 STAGE PLANS 段落——单条 select 1+1 也被规划成 Map Reduce 阶段,Map 侧是对 _dummy_table 的 TableScan 加 Select Operator,表达式 (1 + 1) (type: int) 折叠进 col0,File Output Operator 指向 /tmp/root/hive<时间戳> 目录下的临时文件。两个观察:其一,explain 走的是 Hive 原生规划器,目标目录是 TOK_TMP_FILE 临时目录而非正式执行时 INSERT OVERWRITE DIRECTORY 的句柄目录,说明 explain 不含结果落盘改写,是纯规划视图;其二,它同样没有驱动估计与路由环节的日志,进一步佐证 explain 只回答"Hive 会怎么执行",不回答"Lens 会选哪个驱动"。元数据侧的命令族在空环境下行为一致:show cubes 回显 No cube found;create database demo 静默成功(无确认输出);use demo 回显 Successfully switched to demo。组合起来可以验证元数据服务与数据库命名空间工作正常,这也是部署后端到端检查的常用最小集。

五、真实报错回显与排障路径

报错一:非 Hive 语法的查询。提交含 VALUES 子句的 SQL:

lens-shell>query execute select 1+1 from (values(0)) t(x)
14 Oct 2026 21:18:05,416 [Spring Shell] INFO  cliLogger  - Query handle: 13567647-5494-4dee-b320-d6892e54c7d8
14 Oct 2026 21:18:05,670 [Spring Shell] INFO  cliLogger  - User query: 'select 1+1 from (values(0)) t(x)' was submitted to null
Query Id: 13567647-5494-4dee-b320-d6892e54c7d8
Error Code: 3001
Error Message: Syntax Error: line 1:17 cannot recognize input near 'values' '(' '0' in subquery source

结论明确:Lens 对所有查询先做 Hive 语法解析,解析失败返回错误码 3001 并带解析器定位(line 1:17),改写为 Hive 方言即可。报错二:查询执行阶段的 MapReduce 子任务失败。表现为 CLI 端 Command failed java.lang.NullPointerException,此时应直接到服务端查询日志定位:server/query_logs/<会话句柄>/<操作句柄>.err 文件中记录着真实根因,实测为:

Error: JAVA_HOME is not set and could not be found.
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask

在 lens-env.sh 中 export JAVA_HOME 并重启服务后该问题消失,查询成功执行。这两条路径合起来构成 Lens 查询排障的标准动线:先看 CLI 回显的错误码与定位,再进服务端 query_logs 看操作级 .err 文件,最后对照服务主日志 lensserver.log 的驱动路由与估计环节。

服务端 query_logs 目录的组织结构值得画一张速查图。该目录按 CLI 会话句柄分组(实测部署验证期间积累出三个会话目录,每次管道执行各生成一个),每个会话目录内部按操作句柄存放 .out 与 .err 两个文件:.out 记录操作的标准输出(含查询结果片段),.err 记录标准错误(失败查询的真实报错都在这里)。文件名中的 UUID 与 CLI 回显的句柄一一对应,因此"拿到句柄"就等于拿到了全链路证据的索引——从 CLI 报错回显中的 Query handle,可以直接跳到 query_logs 下的同名文件,再从 lensserver.log 中 grep 同一句柄拿到编排层日志,三级证据串成一条线。这套结构对事后审计尤其有用:即便查询发生在数天前,只要句柄或时间范围已知,就能完整还原当时的提交人、原始 SQL、驱动改写与失败原因。

落到操作层面,排障动线可以固化为三条 grep:第一条在 CLI 回显中抓 Query handle: 或裸句柄;第二条在 server/logs/lensserver.log 里以句柄为关键词定位编排层事件(路由、估计、状态跃迁按时间序全部可见);第三条在 server/query_logs/<会话句柄>/ 下按操作句柄打开 .err 看驱动侧原文。三条命令全部只依赖句柄这一个输入,因此排障第一步永远是留存句柄——CLI 报错信息再简短,句柄一定在里面。这一动线与本篇第六、七节的命令与日志布局互为表里,配合使用即可覆盖绝大多数查询类故障。

六、查询生命周期命令实战

除同步执行的 query execute 外,查询族命令覆盖完整生命周期。query explain 在不执行的前提下输出执行计划,适合验证建模与改写结果;query execute 的 --async 参数支持异步提交,help query execute 的选项表实测如下:

Keyword:  async
Mandatory: false
Default: false

拿到异步句柄后,生命周期命令逐一实测。query status 查询执行状态,回显两行关键信息:

Status: SUCCESSFUL
Progress: 1.0

状态取值对应 Lens 的查询状态机(NEW、RUNNING、EXECUTED、SUCCESSFUL、FAILED、CANCELED、CLOSED 等),Progress 是 0 到 1 之间的进度比例。query results 拉取结果:

_c0
Results of query stored at : file:/tmp/lensreports/hdfsout/7f2f6529-5565-4f80-8adc-f81b896c3d60 - 3 seconds

可指定 save_location 另存。结果回显的格式固定为三要素:结果列名(_c0 这类 Hive 匿名列)、落盘路径与耗时秒数,脚本解析时按行匹配这三个字段即可;需要结果文件真实内容时直接读路径下的 000000_0,不必解析 CLI 回显。query details 输出的明细最丰富,字段包括 userQuery(原始 SQL)、submittedUser(anonymous)、priority(NORMAL)、selectedDriverClassName(最终执行的驱动全类名)、driverQuery(改写后带 INSERT OVERWRITE DIRECTORY 的完整物理语句)、driverOpHandle(驱动侧操作句柄),以及 submissionTime、launchTime、driverStartTime、driverFinishTime、finishTime 五段毫秒级时间戳——相邻时间戳的差值就是各阶段耗时,做性能归因时直接可读。query kill 终止运行中的查询,query list 列出全部查询,实测列表末行给出 Total number of queries: 5,历史句柄一目了然。

查询列表的过滤语法有几处实测陷阱,值得单独记录。help query list 声明的选项含 state/name/user/fromDate/toDate,但三种调用形态给出三种不同结果:query list --state FINISHED 把请求发到服务端后收到 HTTP 400(FINISHED 不是合法状态枚举,合法值形如 SUCCESSFUL、FAILED);query list --status FINISHED 在客户端即被拒绝,回显 Option 'status' is not available for this command,说明选项名必须是 state;不带连字符的 query list state FINISHED 则报 Option 后接空名的 is not available 提示,CLI 把第二个词当成了未注册的命令选项。三条回显合起来把这套过滤器的正确用法夹逼出来:选项用 --state 前缀、值取合法状态枚举、与查询正文无关。同理,省略句柄参数调用 query status 时会得到一条很好的帮助性报错:You should specify a default option (otherwise known as option 'query_handle') for this command,指出这是必填的默认选项。

服务端对这些操作同样有 REST 对应物(/lensapi/query/ 前缀),CLI 本质是 REST 的会话式封装。运维视角的建议:把句柄记录进工单或日志系统,Lens 的结果目录按句柄命名,事后追溯结果文件、操作日志、状态变化都以句柄为键贯穿,这是 Lens 查询体系最值得沿用的设计。此外 show nativetables 在空环境下的回显为 No nativetable found,说明 CLI 对"空结果"与"命令错误"有明确区分——前者正常返回提示,后者走 Command failed 路径,脚本化时可以据此设计分支逻辑。

七、服务端运维配合动作

CLI 之外,配套的服务端运维动作直接影响查询实战。启动与停止用 server/bin/lens-ctl start|stop,实测停止输出 Stopped lens server!,停止后 9999 端口连接被拒(curl 返回 000),确认进程干净退出。健康检查用 GET /lensapi/admin/status(返回 STARTED)与 /lensapi/admin/stack(线程栈快照,排查挂起时直接可用)。日志体系分三层:服务主日志 lensserver.log(含版本横幅、服务初始化、驱动加载、查询全链路)、请求日志 lensserver-requests.log(逐请求方法与路径)与 query_logs 会话目录(操作级 .err/.out)。堆内存经 lens-env.sh 的 LENS_SERVER_HEAP 设置(实测 -Xms256m -Xmx512m),用 ps -ef | grep [j]ava 确认进程参数生效。查询结果与临时产物在 /tmp/lensreports 下按句柄积累,日常运维应配置定期清理,避免磁盘被历史结果占满。

第四层是查询统计日志 query-stats.log,它把每条查询的生命周期档案以一行 JSON 落盘,实测条目形如:

{"eventTime":1792017259077,"handle":"7f2f6529-5565-4f80-8adc-f81b896c3d60","userQuery":"select 1+2","submitter":"anonymous","clusterUser":"root","sessionId":"2dbd2e04-95e5-4dbc-bbd1-f0cf014e8bdc","submissionTime":1792017256049,"startTime":1792017256171,"endTime":1792017259077,"status":{"progress":1.0,"status":"SUCCESSFUL","statusMessage":"Query is successful!","resultSetAvailable":true},"cause":"","driverStats":{"driverQuery":"INSERT OVERWRITE DIRECTORY \"file:/tmp/lensreports/hdfsout/7f2f6529-5565-4f80-8adc-f81b896c3d60\"  select 1+2 ","startTime":1792017256147,"endTime":1792017256147},"eventId":"queryExecutionStatistics"}

字段与 query details 的明细一一对应(userQuery、submitter、clusterUser、sessionId、各时间戳),status 子对象携带 progress 与最终状态,driverStats 子对象甚至内嵌了改写后的驱动语句全文,且按小时轮转出 query-stats.log.2026-10-14-20 这类带时间后缀的归档文件。对脚本化审计而言,这是比 query_logs 更好消费的数据源:一条 jq 命令即可统计某时段的查询量、失败率与平均耗时,不必逐文件解析。它同时印证了前文两个身份字段的实际取值路径——submitter 恒为 anonymous、clusterUser 为 root,与会话参数回显一致。

升级与回滚层面,由于项目已退役,实操建议是冻结当前版本、只做环境级变更:变更前记录 lens-site.xml 与 lens-env.sh 的基线、停止服务、备份 query_logs 与结果目录,再执行变更并复跑本节的端到端验证命令。

请求日志的细节能力超出一般"访问日志"的范畴,联调时可以把它当轻量抓包工具用。lensserver-requests.log 的每个条目都是一次完整的 HTTP 交互转储:请求方法与完整路径、查询字符串、请求头与载荷、响应状态行与响应体。CLI 的每个动作在这里都有对应条目——例如一条 query execute 会展开为会话参数传递与查询提交两笔请求,从转储内容可以直接看出 CLI 拼装的参数顺序与 URL 编码形态。这带来一个实用的联调方法论:当 REST 客户端与 CLI 行为不一致时,先跑 CLI 复现成功场景,再到请求日志里抄下 CLI 实际发出的请求形态,对照排查自己的 REST 调用差异,通常一轮就能定位。日志体量方面,转储粒度细意味着增长快,长期运行环境应给它单独配置轮转策略,避免它反向吞噬排障所需的其它日志空间。

八、常见问题(FAQ)

1. CLI 有没有 connect 命令? 没有独立的连接命令。首条需要服务端的命令会自动建立会话,帮助列表中的 close/bye 负责释放会话退出。会话参数可用 show params 验证。

2. 提交查询报 Error Code: 3001 是什么意思? Hive 语法解析失败。Lens 对所有查询先按 Hive 方言解析,实测非 Hive 写法(如 VALUES 子句)被拒并给出行列定位,改写为 Hive 方言后重试即可。

3. 查询提交后 CLI 显示 Command failed NullPointerException 怎么办? CLI 侧的空指针通常是驱动侧执行失败的表现,应到服务端 server/query_logs/<会话>/<操作>.err 查看真实根因,实测一例为 MapReduce 子进程缺 JAVA_HOME,补齐环境变量后恢复。

4. 查询结果存放在哪里? 统一改写为 INSERT OVERWRITE DIRECTORY 落盘到 /tmp/lensreports/hdfsout/<查询句柄>,CLI 回显该路径与耗时;结果文件为纯文本,可直接查看或被下游程序消费。

5. 为什么我的查询被路由到 HiveDriver 而不是 JDBC 驱动? 双驱动并存时按代价估计路由,估计失败的驱动退出候选。实测默认 JDBC 配置(指向 MySQL 且 URI 为空)估计阶段抛空指针,查询由 HiveDriver 承接;如需启用 JDBC 驱动,应在 lens-site.xml 配置 driver.class 与 db.uri 并验证估计通过。

6. 异步查询怎么用? 用 Spring Shell 选项语法 query execute --async true select 1+2 提交,立即返回裸查询句柄;随后用 query status 轮询、query results 取数、query kill 可终止。注意开关必须带 -- 前缀,实测把 async true 写进查询正文会被整体当作 SQL 提交并以 3001 语法错误告终。同步模式默认等待执行完成直接回显结果。

7. 如何确认服务端健康? GET /lensapi/admin/status 返回 STARTED 即服务正常;/lensapi/admin/stack 可获取线程栈用于挂起排查;CLI 能否自动建会话并返回 show databases 结果也是有效的端到端健康信号。

8. 建模命令(create cube 等)需要什么输入? 均以 XML 规格文件为输入(<path-to-cube-spec-file>),先准备立方体/事实/维度表/存储的 XSD 合法文档再执行;建模对象通过 describe/show 命令检视,属于元数据操作,无需重启服务。

9. 会话里的 add jar 有什么用? 向服务端会话注册 jar 与文件资源,查询执行时在驱动端加载,典型用途是注册自定义 UDF;会话关闭即释放,长期使用的资源应在服务端配置中管理。

10. 结果目录会无限增长吗? 会。/tmp/lensreports 按查询句柄积累,生产化运维应配置清理策略或定期归档;迁移/巡检时注意保留正在排队或引用中的句柄对应结果。

11. query list 的过滤参数为什么总报错? 三层校验要同时对上:选项名必须是 --state(写成 --status 在客户端即被拒,报 Option 'status' is not available);值必须是 Lens 状态枚举(SUCCESSFUL、FAILED 等,写 FINISHED 会被服务端以 HTTP 400 拒绝);选项与值之间用空格分隔且带连字符前缀。省略句柄调用 query status 的报错也属同类——You should specify a default option 指的就是必填的 query_handle。

12. CLI 能执行操作系统命令吗? 不能。虽然帮助文本提示 ! 前缀可执行系统命令,实测该版本并未注册该桥接,输入 !echo 得到 Command not found 回显。需要 shell 操作时应另开终端,编写自动化脚本时不要依赖该特性。

13. 异步句柄的回显为什么没有 Query handle 前缀? 同步模式在执行完成后回显带前缀的日志行;异步模式立即返回的只有句柄本身(裸 UUID),便于脚本直接截取。两种模式回显格式的差异是实测确认的行为,做结果解析时要分别处理。

参考链接