如何与 OSConfig 和 Azure IoT 的 CommandRunner 功能交互

OSConfig 公开的大多数设备属性都是离散的,从实现详细信息中抽象出来。 例如,使用 HostName.desiredName 设置设备的主机名时,无需担心操作系统风格、脚本运行时依赖项或计时细微差别。

但是,有时你可能希望以简单性来换取灵活性。 例如:

  • 你需要从设备中检索自定义信息,例如想要从设备的角度报告 的结果ping example.com
  • 你需要在没有现有 OSConfig 所需/可写属性的设备上配置某些内容

OSConfig 的 CommandRunner 功能通过 shell 命令/脚本启用自定义配置和报告。 它还包括某些预定义的操作, (关闭、重启) 不需要任何脚本。

提示

此参考文章介绍 CommandRunner 概念、交互模型等。有关具体用法示例,请参阅:

交互模型和关键属性/字段

交互模型摘要

虽然 (和本文后面部分) 中介绍的更细微的用法,但核心交互模型非常简单:

  • 通过写入孪生体中的所需 commandArguments 来启动命令请求。
  • 通过从孪生体中读取报告 commandStatus 来获取结果。

显示 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 触发器。

  1. 后台刷新

    commandStatus 将定期更新, (默认值为 30 秒) 。 默认情况下,此后台刷新会导致它表示最新请求的状态。

    实际上,这意味着通过 commandArguments 提交请求后,预计大约 30-60 秒后,commandStatus 中会出现相应的状态。

  2. refreshCommandStatus

    refreshCommandStatus 是一种解决两个高级用例的机制:

    1. 随着时间的推移,你通过 commandArguments发出了多个请求,并且你希望查看特定请求的状态,而不是最近的请求
    2. 你不想等待后台刷新,即使你只对最新请求感兴趣

    若要触发此机制,请参阅下面的对象模型文档。commandArguments

使用 CommandRunner 进行自定义配置和报告的良好做法

  1. 大小注意事项

    对于短命令/脚本和短输出,可以通过孪生体直接内联工作。 此方法具有优势,尤其是在IoT 中心之外没有网络或身份验证依赖项。 此方法的主要缺点是输入 ((包括脚本/命令文本) )和输出 (包括任何捕获的控制台输出) 均限制为 4KB。

    对于较长的脚本,可以将脚本存储在其他位置 ((例如 GitHub) ),并从通过孪生传递给 OSConfig 的最小包装器命令调用该脚本。 有关示例,请参阅: 使用 Azure IoT 和 OSConfig 进行自定义配置和报告。 与大小无关,你可能还更愿意在 GitHub 或类似内容中管理脚本- 孪生体内容仅指向这些内容。

    对于控制台输出对于孪生来说太大的脚本/命令,可以在脚本中包含逻辑,以便将结果发送到本地或云存储,而不是发送到 stdout。 有关示例,请参阅: 使用 Azure IoT 和 OSConfig 进行自定义配置和报告

  2. 使用自包含的非交互式命令/脚本

    往返次数越少越好,一次往返最好。 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 中心和真实设备的示例

重要

2022 年 6 月 28 日发布的版本 1.0.3 () 包括对成员名称的重大更改,这些更改可能会影响现有用户。 有关详细信息,请参阅: 成员名称在版本 1.0.3 中从 PascalCase 转换到 camelCase

后续步骤

有关 OSConfig 方案和功能的概述,请参阅:

有关具体的实际示例,请参阅: