如何与 OSConfig 和 Azure IoT 的 CommandRunner 功能交互
OSConfig 公开的大多数设备属性都是离散的,从实现详细信息中抽象出来。 例如,使用 HostName.desiredName
设置设备的主机名时,无需担心操作系统风格、脚本运行时依赖项或计时细微差别。
但是,有时你可能希望以简单性来换取灵活性。 例如:
- 你需要从设备中检索自定义信息,例如想要从设备的角度报告 的结果
ping example.com
- 你需要在没有现有 OSConfig 所需/可写属性的设备上配置某些内容
OSConfig 的 CommandRunner 功能通过 shell 命令/脚本启用自定义配置和报告。 它还包括某些预定义的操作, (关闭、重启) 不需要任何脚本。
提示
此参考文章介绍 CommandRunner 概念、交互模型等。有关具体用法示例,请参阅:
交互模型和关键属性/字段
交互模型摘要
虽然 (和本文后面部分) 中介绍的更细微的用法,但核心交互模型非常简单:
- 通过写入孪生体中的所需
commandArguments
来启动命令请求。 - 通过从孪生体中读取报告
commandStatus
来获取结果。
重要
此图中显示的有效负载被剥离,以强调传入/传出流。 有关完整对象模型(包括此处未显示的必要成员),请参阅: 完整对象模型
往返标识符为: commandId
在上图中,请注意 和 commandStatus
都包含commandArguments
一个名为 的commandId
字段。 这是在整个异步操作中链接请求和结果的往返标识符。
调用方 (管理员或管理工具链) 选择 commandId 值。
提示
commandId
在 中 commandArguments
是必需的。 调用方在选择值时通常使用以下模式之一:
第一个请求) 的“1” (、第二个请求) 的“2” (等单调值。或描述性值,如“my_ping_command”
这些非常适合临时探索:它们不需要规划,并且可以在编辑孪生体内容时轻松键入
高熵自动生成的值,如 UUID
它们非常适合大规模编程使用,其中云解决方案后端将以编程方式创建并跟踪值
中的 commandArguments
新值commandId
指示这是一个新请求。 在单个设备的孪生体上下文中,填充新的 commandId
大致类似于在 shell 环境中按“Enter”。
commandId
还允许跟踪多个请求。 每台设备上的 CommandRunner 可以接收 (,并报告一段时间内) 多个请求的状态。 同时, commandArguments
每个设备孪生中的 和 commandStatus
组件在任何时候只能描述一个请求。 commandId
是往返标识符,使调用方能够了解 (和控制) 上一个请求当前由 commandStatus
描述。 实际上, commandStatus
会传达“对于 ID 为 'foo' 的请求,状态为 <...>”。
commandStatus
何时更新?
设备上有两个用于更新 commandStatus
的 CommandRunner 触发器。
后台刷新
commandStatus
将定期更新, (默认值为 30 秒) 。 默认情况下,此后台刷新会导致它表示最新请求的状态。实际上,这意味着通过 commandArguments 提交请求后,预计大约 30-60 秒后,commandStatus 中会出现相应的状态。
refreshCommandStatus
refreshCommandStatus
是一种解决两个高级用例的机制:- 随着时间的推移,你通过
commandArguments
发出了多个请求,并且你希望查看特定请求的状态,而不是最近的请求 - 你不想等待后台刷新,即使你只对最新请求感兴趣
若要触发此机制,请参阅下面的对象模型文档。
commandArguments
- 随着时间的推移,你通过
使用 CommandRunner 进行自定义配置和报告的良好做法
大小注意事项
对于短命令/脚本和短输出,可以通过孪生体直接内联工作。 此方法具有优势,尤其是在IoT 中心之外没有网络或身份验证依赖项。 此方法的主要缺点是输入 ((包括脚本/命令文本) )和输出 (包括任何捕获的控制台输出) 均限制为 4KB。
对于较长的脚本,可以将脚本存储在其他位置 ((例如 GitHub) ),并从通过孪生传递给 OSConfig 的最小包装器命令调用该脚本。 有关示例,请参阅: 使用 Azure IoT 和 OSConfig 进行自定义配置和报告。 与大小无关,你可能还更愿意在 GitHub 或类似内容中管理脚本- 孪生体内容仅指向这些内容。
对于控制台输出对于孪生来说太大的脚本/命令,可以在脚本中包含逻辑,以便将结果发送到本地或云存储,而不是发送到 stdout。 有关示例,请参阅: 使用 Azure IoT 和 OSConfig 进行自定义配置和报告。
使用自包含的非交互式命令/脚本
往返次数越少越好,一次往返最好。 OSConfig 和 CommandRunner 针对缩放而非交互性进行优化。 尽管可以连续 (一个命令使用 CommandRunner,但类似于实时同步终端,) 体验不是最佳的。 无法处理交互式 shell 提示,必须为每个请求分配 ,
commandId
必须等待孪生同步,等等。相反,请将 CommandRunner 视为实现大规模自定义配置和报告的一种方式。 可以将非交互式脚本 (或预定义的操作(如重启) )异步分发到一个设备或数百万台设备,并且可以报告结果,即使随着新设备加入机群(例如) )随时间推移而变化 (结果。
换句话说,假设需要在西班牙的所有当前和将来的 Ubuntu 20.04 设备上运行四个命令。 不要将其视为 CommandRunner 的 4 个离散顺序使用,请将其视为 CommandRunner 的一次性使用,其中有效负载包含四个命令。 同时,云工作流(如IoT 中心配置)可确保将其分发到所有当前和将来的设备,这些设备应处于范围内。
完整的对象模型
重要
2022 年 6 月 28 日发布的版本 1.0.3 () 包括对成员名称的重大更改,这些更改可能会影响现有用户。 有关详细信息,请参阅: 成员名称在版本 1.0.3 中从 PascalCase 转换到 camelCase
以下信息适用于对象模型的普通所需/报告视图以及 DTDL 增强视图。 有关详细信息,请参阅 OSConfig 用户需要了解有关“纯所需/报告”与“DTDL 增强型”工具链的信息。
commandArguments (由管理员) 设置
说明:来自管理员的输入,触发新的命令请求或触发 commandStatus 的刷新。
路径:
properties.desired.CommandRunner.commandArguments
(CommandRunner
组件 -->commandArguments
可写属性)成员
名称 类型 说明 commandId 字符串 • 调用方指定的请求 ID;有关背景,请参阅上文
• 当 commandId 为空时,将忽略 commandArguments
• 有关 commandId 和 action 之间的交互,请参阅以下内容action enum/int 应将以下内容与 commandId 的新值结合使用:
• 1 个 (重启)
• 2 个 (关闭)
• 3 (runCommand) ;启动用于自定义配置或报告的 shell 命令/脚本
应将以下内容与以前使用的 CommandID 结合使用:
• 4 (refreshCommandStatus) 会导致 commandStatus 描述由 commandId 标识的特定请求参数 string • 当操作为 1 (重新启动) 或 2 (关闭) 时,在触发操作之前需要延迟的可选秒数
• 如果 action 为 3 (RunCommand) ,则为要执行的命令行,例如ping -c 2 example.com
• 忽略任何其他操作类型
• commandArguments 的大小 (通常由 Azure IoT 孪生体中的参数文本) 主导,限制为 4KB;有关较长脚本,请参阅 良好做法singleLineTextResult boolean • 当操作为 3 (RunCommand) 时,可选切换以指定是否应从控制台输出中删除换行符
• 忽略任何其他操作类型timeout int • 当 action 为 3 (runCommand) 时,长时间运行的请求在几秒钟后终止
• 可选 (默认值为 30)
• 忽略任何其他操作类型来自IoT 中心和真实设备的示例
重新启动请求:
"CommandRunner": { "__t": "c", "commandArguments": { "commandId": "my_reboot_cmd", "arguments": "", "timeout": 30, "singleLineTextResult": false, "action": 1 } }
自定义配置 (时区) 请求:
"CommandRunner": { "__t": "c", "commandArguments": { "commandId": "my_timezone_cmd", "arguments": "timedatectl set-timezone Etc/UTC; timedatectl | grep Time", "timeout": 30, "singleLineTextResult": false, "action": 3 } }
有关其他示例,请参阅:
commandArguments 从设备) (确认
说明:这是来自设备上的 OSConfig 代理的确认,它已从管理员端收到 commandArguments 值
路径:
properties.reported.CommandRunner.commandArguments
(可写属性) 的设备commandArguments
确认部分成员:
名称 类型 说明 value 映射 应镜像 properties.desired.CommandRunner.commandArguments
,指示设备处于联机状态并已收到请求ac int 状态代码,名义大小写为值 200
commandStatus
说明:提供之前通过 commandArguments 提交的请求的状态和输出
路径:
properties.reported.CommandRunner.commandStatus
(CommandRunner
组件 -->commandStatus
只读属性)成员
名称 类型 说明 commandId 字符串 • 标识 Commandstatus 当前描述了以前收到的请求
• 默认情况下,表示最新的请求
• 调用方可以通过上述 refreshCommandStatus 机制更改此焦点来描述特定请求resultCode int 所请求命令的退出代码。 类似于 echo $?
bash 中的currentState enum/int • 名义大小写为值 2
(succeeded
)
• 有关可能值的完整列表,请参阅元数据textResult 字符串 • 所请求命令的控制台输出
• commandStatus 的大小 (通常由 azure IoT 孪生中的 textResult 组件) 主导,限制为 4KB;有关较长输出,请参阅 良好做法来自IoT 中心和真实设备的示例
重新启动结果
"CommandRunner": { "__t": "c", "commandStatus": { "commandId": "my_reboot_cmd", "resultCode": 0, "textResult": "", "currentState": 2 } }
自定义配置 (时区) 结果:
"CommandRunner": { "__t": "c", "commandStatus": { "commandId": "my_timezone_cmd", "testResult": "Time zone: UTC", "statusCode": 0 } }
有关其他示例,请参阅:
重要
2022 年 6 月 28 日发布的版本 1.0.3 () 包括对成员名称的重大更改,这些更改可能会影响现有用户。 有关详细信息,请参阅: 成员名称在版本 1.0.3 中从 PascalCase 转换到 camelCase
后续步骤
有关 OSConfig 方案和功能的概述,请参阅:
有关具体的实际示例,请参阅: