Como interagir com o recurso CommandRunner do OSConfig e do Azure IoT
A maioria das propriedades do dispositivo expostas pelo OSConfig é discreta e abstraída dos detalhes da implementação. Por exemplo, quando você usa HostName.desiredName
para definir o nome do host de um dispositivo, não precisa se preocupar com o tipo de sistema operacional, com relação a dependências de runtime de script ou com nuances de tempo.
Às vezes, no entanto, talvez você queira trocar a simplicidade por flexibilidade. Por exemplo:
- Você precisa recuperar informações personalizadas do dispositivo , como querer relatar os resultados da
ping example.com
perspectiva do dispositivo - Você precisa configurar algo no dispositivo em que não há nenhuma propriedade desejada/gravável do OSConfig existente
O recurso CommandRunner do OSConfig habilita a configuração personalizada e os relatórios por meio de comandos/scripts do shell. Ele também inclui determinadas ações predefinidas (desligamento, reinicialização) que não exigem nenhum script.
Dica
Este artigo de referência descreve os conceitos do CommandRunner, o modelo de interação etc. Para obter exemplos concretos de uso, consulte:
O modelo de interação e as principais propriedades/campos
Resumo do modelo de interação
Embora seja possível usar mais nuances (e descrito posteriormente neste artigo), o modelo de interação principal é simples:
- Você inicia uma solicitação de comando gravando o desejado
commandArguments
no gêmeo. - Você obtém os resultados lendo relatados
commandStatus
do gêmeo.
Importante
As cargas mostradas neste diagrama são removidas para enfatizar o fluxo de entrada/saída. Para o modelo de objeto completo, incluindo membros necessários não mostrados aqui, consulte: O modelo de objeto completo
O identificador de ida e volta é: commandId
No diagrama acima, observe que e commandArguments
commandStatus
incluem um campo chamado commandId
. Esse é o identificador de ida e volta que vincula a solicitação e o resultado ao longo dessa operação assíncrona.
O chamador (administrador ou cadeia de ferramentas de administrador) escolhe o valor commandId.
Dica
commandId
é necessário em commandArguments
. Os chamadores normalmente usam um desses padrões ao escolher valores:
Valores monotônicos como "1" (para primeira solicitação), "2" (para segunda solicitação), etc. ou valores descritivos como "my_ping_command"
Eles são adequados para exploração ad hoc; eles não exigem planejamento e podem ser digitadas facilmente ao editar conteúdo de gêmeos
Valores de alta entropia gerados automaticamente, como UUIDs
Eles são adequados para uso programático em larga escala, em que um back-end de solução de nuvem criará e manterá o controle de valores programaticamente
Um novo valor de commandId
em commandArguments
sinaliza que essa é uma nova solicitação. No contexto do gêmeo de um único dispositivo, preencher um novo commandId
é aproximadamente análogo a atingir 'Enter' em um ambiente de shell.
commandId
também permite manter o controle de várias solicitações. O CommandRunner em cada dispositivo pode receber (e relatar status) várias solicitações ao longo do tempo. Enquanto isso, os commandArguments
componentes e commandStatus
no gêmeo de cada dispositivo só podem descrever uma solicitação a qualquer momento. commandId
é o identificador de viagem de ida e volta que permite que o chamador entenda (e controle) qual solicitação anterior está descrita atualmente por commandStatus
. Na verdade, commandStatus
comunica "para sua solicitação em que a ID era 'foo', o status é <...>".
Quando é commandStatus
atualizado?
Há dois gatilhos para CommandRunner no dispositivo atualizar commandStatus
.
Atualização em segundo plano
commandStatus
é atualizado em um intervalo regular (o padrão é 30 segundos). Por padrão, essa atualização em segundo plano faz com que ela represente o status da solicitação mais recente.Na prática, isso significa que, depois de enviar uma solicitação por meio de commandArguments, você pode esperar ver status correspondentes em commandStatus após aproximadamente 30 a 60 segundos.
refreshCommandStatus
refreshCommandStatus
é um mecanismo que aborda dois casos de uso avançados:- Você emitiu várias solicitações ao longo do tempo por meio
commandArguments
de e deseja ver o status para uma solicitação específica, não a solicitação mais recente - Você não deseja aguardar a atualização em segundo plano, mesmo que esteja interessado apenas na solicitação mais recente
Para disparar esse mecanismo, consulte a documentação do modelo de objeto abaixo para
commandArguments
.- Você emitiu várias solicitações ao longo do tempo por meio
Boas práticas para configuração personalizada e relatórios com CommandRunner
Considerações de tamanhos
Para comandos/scripts curtos e saídas curtas, você pode trabalhar diretamente embutido por meio do gêmeo. Essa abordagem tem vantagens, especialmente sem dependência de rede ou autenticação fora do Hub IoT. A principal desvantagem dessa abordagem é que as entradas (incluindo o texto de script/comandos) e as saídas (incluindo qualquer saída de console capturada) são limitadas a 4 KB.
Para scripts mais longos, você pode armazenar o script em outro lugar (como o GitHub) e chamá-lo de um comando wrapper mínimo que você passa para OSConfig sobre o gêmeo. Para obter exemplos, consulte: Configuração e relatórios personalizados com o Azure IoT e OSConfig. Independentemente do tamanho, você também pode preferir gerenciar seus scripts no GitHub ou semelhantes, com conteúdo de gêmeo simplesmente apontando para eles.
Para scripts/comandos cuja saída do console é muito grande para o gêmeo, você pode incluir lógica no script para enviar resultados para o armazenamento local ou na nuvem em vez de stdout. Para obter exemplos, consulte: Configuração e relatórios personalizados com o Azure IoT e OSConfig.
Usar comandos/scripts independentes e não interativos
Menos viagens de ida e volta são melhores, uma viagem de ida e volta é melhor. OSConfig e CommandRunner são otimizados para escala e não interatividade. Embora seja possível usar o CommandRunner serialmente (um comando após o outro, semelhante a um terminal síncrono dinâmico), a experiência não é ideal. Não há como lidar com prompts de shell interativos, você deve atribuir um
commandId
a cada solicitação, você deve aguardar a sincronização de gêmeos etc.Em vez disso, pense no CommandRunner como uma maneira de obter configuração personalizada e relatórios em escala. Você pode distribuir de forma assíncrona um script não interativo (ou uma ação predefinida, como reinicialização) para um dispositivo ou milhões de dispositivos e pode relatar os resultados mesmo conforme eles evoluem ao longo do tempo (à medida que novos dispositivos ingressam na frota, por exemplo).
Em outras palavras, digamos que você precise executar quatro comandos em todos os dispositivos Ubuntu 20.04 atuais e futuros na Espanha. Não pense nisso como quatro usos sequenciais discretos do CommandRunner, pense nisso como um único uso do CommandRunner em que o conteúdo contém seus quatro comandos. Enquanto isso, um fluxo de trabalho de nuvem, como configurações de Hub IoT, pode garantir que isso seja distribuído para todos os dispositivos atuais e futuros que devem estar no escopo.
O modelo de objeto completo
Importante
A versão 1.0.3 (publicada em 28 de junho de 2022) inclui alterações interruptivas nos nomes dos membros que podem afetar os usuários existentes. Para obter mais informações, consulte: Transição de nomes de membro de PascalCase para camelCase na versão 1.0.3
As informações a seguir se aplicam a exibições simples desejadas/relatadas do modelo de objeto, bem como exibições aprimoradas de DTDL. Para obter mais informações, consulte O que os usuários do OSConfig precisam saber sobre cadeias de ferramentas "simples desejadas/relatadas" versus "DTDL aprimorada".
commandArguments (definido pelo administrador)
Descrição: a entrada do administrador dispara uma nova solicitação de comando ou dispara a atualização de commandStatus.
Caminho:
properties.desired.CommandRunner.commandArguments
(CommandRunner
componente –>commandArguments
propriedade gravável)Membros
Nome Type Observações commandId string • ID de solicitação especificada pelo chamador; consulte acima para obter a tela de fundo
• commandArguments é ignorado quando commandId está em branco
• Para interação entre commandId e action, consulte o seguinteação enum/int O seguinte deve ser acoplado a um novo valor de commandId:
• 1 (reinicialização)
• 2 (desligamento)
• 3 (runCommand); inicia o comando/script do shell para configuração ou relatórios personalizados
O seguinte deve ser acoplado a um CommandID usado anteriormente:
• 4 (refreshCommandStatus) faz com que commandStatus descreva uma solicitação específica identificada por commandIdargumentos string • Quando a ação é 1 (reinicialização) ou 2 (desligamento), um número opcional de segundos para atrasar antes de disparar a ação
• Quando a ação é 3 (RunCommand), a linha de comando a ser executada, por exemploping -c 2 example.com
• Ignorado para qualquer outro tipo de ação
• Tamanho de commandArguments (geralmente dominado pelo texto de argumentos) nos gêmeos IoT do Azure em limitado a 4 KB; para scripts mais longos, confira Boas práticassingleLineTextResult booleano • Quando a ação for 3 (RunCommand), alternância opcional para especificar se as novas linhas devem ser removidas da saída do console
• Ignorado para qualquer outro tipo de açãotempo limite INT • Quando a ação for 3 (runCommand), as solicitações de execução prolongada serão encerradas após esses muitos segundos
• Opcional (o padrão é 30)
• Ignorado para qualquer outro tipo de açãoExemplos de Hub IoT e dispositivos reais
Solicitação de reinicialização:
"CommandRunner": { "__t": "c", "commandArguments": { "commandId": "my_reboot_cmd", "arguments": "", "timeout": 30, "singleLineTextResult": false, "action": 1 } }
Solicitação de configuração personalizada (fuso horário):
"CommandRunner": { "__t": "c", "commandArguments": { "commandId": "my_timezone_cmd", "arguments": "timedatectl set-timezone Etc/UTC; timedatectl | grep Time", "timeout": 30, "singleLineTextResult": false, "action": 3 } }
Para obter exemplos adicionais, consulte:
commandArguments (confirmação do dispositivo)
Descrição: essa é a confirmação do agente OSConfig no dispositivo de que ele recebeu o valor commandArguments do lado do administrador
Caminho:
properties.reported.CommandRunner.commandArguments
(a parte de confirmação do dispositivo dacommandArguments
propriedade gravável)Membros:
Nome Type Observações value mapa Deve espelho properties.desired.CommandRunner.commandArguments
, indicando que o dispositivo está online e recebeu a solicitaçãoac INT Código de status, maiúsculas e minúsculas nominais é valor 200
commandStatus
Descrição: fornece o status e a saída de uma solicitação enviada anteriormente por meio de commandArguments
Caminho:
properties.reported.CommandRunner.commandStatus
(CommandRunner
componente –>commandStatus
propriedade somente leitura)Membros
Nome Type Observações commandId string • Identifica qual solicitação recebida anteriormente está descrita atualmente por Commandstatus
• Por padrão, a solicitação mais recente é representada
• O chamador pode alterar esse foco para descrever uma solicitação específica por meio do mecanismo refreshCommandStatus descrito acimaresultCode INT O código de saída do comando solicitado. Análogo a echo $?
em bashCurrentstate enum/int • Maiúsculas e minúsculas nominais ( 2
succeeded
)
• Consulte os metadados para obter a lista completa de valores possíveistextResult string • A saída do console do comando solicitado
• Tamanho de commandStatus (geralmente dominado pelo componente textResult) nos gêmeos IoT do Azure em limitado a 4 KB; para saídas mais longas, confira Boas práticasExemplos de Hub IoT e dispositivos reais
Resultado da reinicialização
"CommandRunner": { "__t": "c", "commandStatus": { "commandId": "my_reboot_cmd", "resultCode": 0, "textResult": "", "currentState": 2 } }
Resultado da configuração personalizada (fuso horário):
"CommandRunner": { "__t": "c", "commandStatus": { "commandId": "my_timezone_cmd", "testResult": "Time zone: UTC", "statusCode": 0 } }
Para obter exemplos adicionais, consulte:
Importante
A versão 1.0.3 (publicada em 28 de junho de 2022) inclui alterações interruptivas nos nomes dos membros que podem afetar os usuários existentes. Para obter mais informações, consulte: Transição de nomes de membro de PascalCase para camelCase na versão 1.0.3
Próximas etapas
Para obter uma visão geral dos cenários e funcionalidades do OSConfig, confira:
Para obter exemplos práticos específicos, consulte: