Shell

本节介绍启动 Shell 的选项,以及 Shell 在处理空白字符、引号和 SpEL 表达式解析方面的更高级功能。 有关 Shell 命令最常见用法的入门内容,请参阅Stream DSLComposed Task DSL的入门章节。spring-doc.cadn.net.cn

13. Shell 选项

该 Shell 基于 Spring Shell 项目构建。 某些命令行选项来自 Spring Shell,而另一些则是 Data Flow 特有的。 该 Shell 接受以下命令行选项:spring-doc.cadn.net.cn

unix:>java -jar spring-cloud-dataflow-shell-2.8.3.jar --help
Data Flow Options:
  --dataflow.uri=                              Address of the Data Flow Server [default: http://localhost:9393].
  --dataflow.username=                        Username of the Data Flow Server [no default].
  --dataflow.password=                    Password of the Data Flow Server [no default].
  --dataflow.credentials-provider-command= Executes an external command which must return an
                                                    OAuth Bearer Token (Access Token prefixed with 'Bearer '),
                                                    e.g. 'Bearer 12345'), [no default].
  --dataflow.skip-ssl-validation=       Accept any SSL certificate (even self-signed) [default: no].
  --dataflow.proxy.uri=                  Address of an optional proxy server to use [no default].
  --dataflow.proxy.username=        Username of the proxy server (if required by proxy server) [no default].
  --dataflow.proxy.password=        Password of the proxy server (if required by proxy server) [no default].
  --spring.shell.historySize=                 Default size of the shell log file [default: 3000].
  --spring.shell.commandFile=                 Data Flow Shell executes commands read from the file(s) and then exits.
  --help                                            This message.

你可以使用 spring.shell.commandFile 选项来指向一个已存在的文件,该文件包含用于部署一个或多个相关流(streams)和任务(tasks)的所有 Shell 命令。 也支持运行多个文件,应以逗号分隔的字符串形式传入:spring-doc.cadn.net.cn

--spring.shell.commandFile=file1.txt,file2.txtspring-doc.cadn.net.cn

此选项在创建一些脚本来帮助自动化部署时非常有用。spring-doc.cadn.net.cn

此外,以下 shell 命令有助于将一个复杂的脚本模块化为多个独立的文件:spring-doc.cadn.net.cn

dataflow:>script --file <YOUR_AWESOME_SCRIPT>spring-doc.cadn.net.cn

14. 列出可用命令

在命令提示符处输入 help 可列出所有可用的命令。 大多数命令用于数据流(Data Flow)功能,但也有少数是通用命令。 以下列表展示了 help 命令的输出:spring-doc.cadn.net.cn

! - Allows execution of operating system (OS) commands
clear - Clears the console
cls - Clears the console
date - Displays the local date and time
exit - Exits the shell
http get - Make GET request to http endpoint
http post - POST data to http endpoint
quit - Exits the shell
system properties - Shows the shells properties {JB - restore the apostrophe}
version - Displays shell version

help 中添加命令的名称,将显示有关如何调用该命令的附加信息:spring-doc.cadn.net.cn

dataflow:>help stream create
Keyword:                   stream create
Description:               Create a new stream definition
 Keyword:                  ** default **
 Keyword:                  name
   Help:                   the name to give to the stream
   Mandatory:              true
   Default if specified:   '__NULL__'
   Default if unspecified: '__NULL__'

 Keyword:                  definition
   Help:                   a stream definition, using the DSL (e.g. "http --port=9000 | hdfs")
   Mandatory:              true
   Default if specified:   '__NULL__'
   Default if unspecified: '__NULL__'

 Keyword:                  deploy
   Help:                   whether to deploy the stream immediately
   Mandatory:              false
   Default if specified:   'true'
   Default if unspecified: 'false'

15. 制表符补全

你可以在 shell 中输入前导 TAB 后按 -- 键来自动补全 shell 命令选项。例如,在输入 TAB 后按 stream create -- 键,将得到以下两个建议:spring-doc.cadn.net.cn

dataflow:>stream create --
stream create --definition    stream create --name

如果你输入 --de 然后按 Tab 键,--definition 会展开。spring-doc.cadn.net.cn

在流(stream)或组合任务(composed task)的 DSL 表达式中,应用或任务属性也支持 Tab 自动补全功能。你还可以在流 DSL 表达式中使用 TAB 键,以获取可用的源(sources)、处理器(processors)或接收器(sinks)的提示信息。spring-doc.cadn.net.cn

16. 空白符与引号规则

只有当参数值包含空格或 | 字符时,才需要将其用引号括起来。以下示例将一个 SpEL 表达式(该表达式会应用于其遇到的任何数据)传递给转换处理器:spring-doc.cadn.net.cn

transform --expression='new StringBuilder(payload).reverse()'

如果参数值需要嵌入单引号,请使用两个单引号,如下所示:spring-doc.cadn.net.cn

// Query is: Select * from /Customers where name='Smith'
scan --query='Select * from /Customers where name=''Smith'''

16.1. 引号与转义

有一个基于 Spring Shell 的客户端,用于与 Data Flow Server 通信,并负责解析 DSL。 相应地,应用程序可能具有依赖于嵌入式语言(例如Spring 表达式语言)的应用程序属性。spring-doc.cadn.net.cn

Shell、Data Flow DSL 解析器和 SpEL 对引号的处理方式以及语法转义规则各有规定。 当它们组合使用时,可能会引起混淆。 本节将说明适用的规则,并提供一些在三者共同作用下可能遇到的最复杂情况的示例。spring-doc.cadn.net.cn

并不总是那么复杂

如果您不使用 Data Flow Shell(例如,直接使用 REST API)或者应用程序属性不是 SpEL 表达式,则转义规则会更简单。spring-doc.cadn.net.cn

16.1.1. Shell 规则

可以说,在处理引号时,最复杂的组件是 Shell。不过,其规则却可以非常简单地列出:spring-doc.cadn.net.cn

  • Shell 命令由键(--something)和对应的值组成。不过,还有一种特殊的、无键的映射,稍后将进行说明。spring-doc.cadn.net.cn

  • 值通常不能包含空格,因为空格是命令的默认分隔符。spring-doc.cadn.net.cn

  • 不过,可以通过将值用引号(单引号(')或双引号("))括起来来添加空格。spring-doc.cadn.net.cn

  • 在部署属性中传递的值(例如,deployment <stream-name> --properties " …​")不应再次加引号。spring-doc.cadn.net.cn

  • 如果用引号括起来,值可以通过在相同类型的字面量引号前加上反斜杠(\)来嵌入该引号。spring-doc.cadn.net.cn

  • 还提供了其他转义字符,例如 \t\n\r\f 以及形式为 \uxxxx 的 Unicode 转义序列。spring-doc.cadn.net.cn

  • 无键映射以一种特殊方式处理,因此即使包含空格也无需加引号。spring-doc.cadn.net.cn

例如,shell 支持使用 ! 命令来执行原生 shell 命令。! 接受一个无键参数。这就是以下示例能够正常工作的原因:spring-doc.cadn.net.cn

dataflow:>! rm something

此处的参数是整个 rm something 字符串,它会原封不动地传递给底层的 shell。spring-doc.cadn.net.cn

再举一个例子,以下命令是严格等价的,参数值为something(不带引号):spring-doc.cadn.net.cn

dataflow:>stream destroy something
dataflow:>stream destroy --name something
dataflow:>stream destroy "something"
dataflow:>stream destroy --name "something"

16.1.2. 属性文件规则

从文件加载属性时,规则会更加宽松。spring-doc.cadn.net.cn

  • 属性文件(包括 Java 和 YAML 格式)中使用的特殊字符需要进行转义。例如,\ 应替换为 \\\t 应替换为 \\t,依此类推。spring-doc.cadn.net.cn

  • 对于 Java 属性文件(--propertiesFile <FILE_PATH>.properties),属性值不应使用引号包围。即使属性值中包含空格,也无需使用引号。spring-doc.cadn.net.cn

    filter.expression=payload > 5
  • 然而,对于 YAML 属性文件(--propertiesFile <FILE_PATH>.yaml),其值需要用双引号括起来。spring-doc.cadn.net.cn

    app:
        filter:
            filter:
                expression: "payload > 5"

16.1.3. DSL 解析规则

在解析器级别(即,在流或任务定义的主体内部),规则如下:spring-doc.cadn.net.cn

因此,在以下示例中,过滤器应用程序的 --expression 选项的值在语义上是等价的:spring-doc.cadn.net.cn

filter --expression=payload>5
filter --expression="payload>5"
filter --expression='payload>5'
filter --expression='payload > 5'

可以说,最后一种写法更具可读性。这得益于其周围的引号。实际的表达式是 payload > 5spring-doc.cadn.net.cn

现在,假设我们想要对字符串消息进行测试。如果我们想将有效载荷与 SpEL 字面量字符串 "something" 进行比较,可以使用以下方式:spring-doc.cadn.net.cn

filter --expression=payload=='something'           (1)
filter --expression='payload == ''something'''     (2)
filter --expression='payload == "something"'       (3)
1 这样可以运行,因为其中没有空格。不过,可读性并不好。
2 这使用单引号来保护整个参数。因此,实际的单引号需要写成两个。
3 SpEL 支持使用单引号或双引号来识别字符串字面量,因此最后这种方法可以说是最具可读性的。

请注意,上述示例应被视为在 Shell 外部使用的情况(例如,直接调用 REST API 时)。 当在 Shell 内部输入时,整个流定义很可能本身已包含在双引号内,这时就需要对双引号进行转义。此时,整个示例将变为如下形式:spring-doc.cadn.net.cn

dataflow:>stream create something --definition "http | filter --expression=payload='something' | log"

dataflow:>stream create something --definition "http | filter --expression='payload == ''something''' | log"

dataflow:>stream create something --definition "http | filter --expression='payload == \"something\"' | log"

16.1.4. SpEL 语法与 SpEL 字面量

最后一个问题涉及 SpEL 表达式。 许多应用程序接受被解释为 SpEL 表达式的选项,而且正如前面所见,字符串字面量在那里也会以特殊方式进行处理。其规则如下:spring-doc.cadn.net.cn

  • 字面量可以用单引号或双引号括起来。spring-doc.cadn.net.cn

  • 要嵌入字面量的引号,需要使用两个连续的引号。双引号内的单引号无需特殊处理,反之亦然。spring-doc.cadn.net.cn

作为最后一个示例,假设您想使用transform 处理器。 该处理器接受一个 expression 选项,该选项是一个 SpEL 表达式。此表达式将针对传入的消息进行求值,默认值为 payload(即原样转发消息的有效载荷)。spring-doc.cadn.net.cn

理解以下语句是等价的这一点非常重要:spring-doc.cadn.net.cn

transform --expression=payload
transform --expression='payload'

然而,它们与以下内容(及其变体)不同:spring-doc.cadn.net.cn

transform --expression="'payload'"
transform --expression='''payload'''

第一个表达式求值为消息的有效载荷,而后面的示例则求值为字面量字符串 payloadspring-doc.cadn.net.cn

16.1.5. 整合所有内容

最后,作为一个完整的示例,请考虑如何通过在 Data Flow shell 的上下文中创建一个流,强制将所有消息转换为字符串字面量 hello worldspring-doc.cadn.net.cn

dataflow:>stream create something --definition "http | transform --expression='''hello world''' | log" (1)

dataflow:>stream create something --definition "http | transform --expression='\"hello world\"' | log" (2)

dataflow:>stream create something --definition "http | transform --expression=\"'hello world'\" | log" (2)
1 在第一行中,单引号用于包围字符串(在数据流解析器层面),但由于它们位于字符串字面量内部(由等号后的第一个单引号开始),因此需要使用两个单引号来转义。
2 第二行和第三行分别使用单引号和双引号,在数据流解析器层面将整个字符串括起来。因此,字符串内部可以使用另一种引号。不过,整个内容位于传递给 shell 的 --definition 参数中,而该参数使用双引号,因此双引号在 shell 层面进行了转义。