Extensão de script personalizado para o Windows

A extensão de script personalizado baixa e executa scripts em VMs (máquinas virtuais) do Azure. Use essa extensão para a configuração pós-implantação, instalação de software ou qualquer outra tarefa de configuração ou gerenciamento. Você pode baixar scripts do Armazenamento do Azure ou do GitHub ou fornecê-los ao portal do Azure no runtime de extensão.

A extensão de Script personalizado se integra com os modelos do Azure Resource Manager. Você também pode executá-la usando a CLI do Azure, o PowerShell do Azure, o portal do Azure ou a API REST de Máquinas Virtuais do Azure.

Este artigo descreve como utilizar a Extensão de Script Personalizado usando o módulo do Azure PowerShell e os modelos do Azure Resource Manager. Ele também fornece as etapas de solução de problemas em sistemas Windows.

Pré-requisitos

Observação

Não use a Extensão de Script Personalizado para executar oUpdate-AzVM com a mesma VM que o respectivo parâmetro. A extensão irá esperar por si mesma.

Sistemas operacionais Windows compatíveis

Sistema operacional Windows x64
Windows 10 Com suporte
Windows 11 Com suporte
Windows Server 2008 SP2 Com suporte
Windows Server 2008 R2 Com suporte
Windows Server 2012 Com suporte
Windows Server 2012 R2 Com suporte
Windows Server 2016 Com suporte
Windows Server 2016 Core Com suporte
Windows Server 2019 Com suporte
Windows Server 2019 Core Com suporte
Windows Server 2022 Com suporte
Windows Server 2022 Core Com suporte

Local do script

Você pode configurar a extensão para usar suas credenciais do Armazenamento de Blobs do Azure para acessar esse armazenamento. O local do script pode ser qualquer um, desde que a VM possa rotear para esse ponto de extremidade, como, por exemplo, o GitHub ou um servidor de arquivos interno.

Conectividade com a Internet

Para baixar um script externamente, como, por exemplo, do GitHub ou do Armazenamento do Azure, você precisará abrir outras portas de firewall ou do grupo de segurança de rede (NSG). Por exemplo, se o script estiver localizado no Armazenamento do Azure, você poderá permitir o acesso usando marcas de serviço para armazenamento do NSG do Azure.

A Extensão de Script Personalizado não tem nenhuma forma de ignorar a validação de certificado. Se estiver baixando a partir de um local seguro com, por exemplo, um certificado autoassinado, você pode obtendo erros como O certificado remoto é inválido de acordo com o procedimento de validação. Certifique-se de que o certificado foi instalado corretamente no repositório Autoridades Confiáveis de Certificação Raiz da máquina virtual.

Se o seu script estiver em um servidor local, talvez você continue precisando abrir outras portas de firewall ou de NSG.

Dicas

  • A saída está limitada aos últimos 4.096 bytes.
  • Fazer o escape correto de caracteres ajudará a garantir que as cadeias de caracteres sejam analisadas corretamente. Por exemplo, ao lidar com caminhos de arquivo, é necessário usar duas barras invertidas para escapar uma única barra invertida literal. Exemplo: {"commandToExecute": "C:\\Windows\\System32\\systeminfo.exe >> D:\\test.txt"}
  • A taxa de falha mais alta para essa extensão ocorre devido a erros de sintaxe no script. Verifique se o script está sendo executado sem erros. Coloque mais registros em log no script para facilitar a detecção de falhas.
  • Escreva scripts idempotentes, de modo que executá-los mais de uma vez inadvertidamente não cause alterações no sistema.
  • Verifique se os scripts não exigem entrada de usuário quando são executados.
  • O script tem permissão para ser executado em 90 minutos. Qualquer coisa além disso resultará em falha no provisionamento da extensão.
  • Não inclua reinicializações dentro do script. Essa ação causará problemas com outras extensões que estiverem sendo instaladas e a extensão não continuará após a reinicialização.
  • Se tiver um script que cause uma reinicialização antes de instalar aplicativos e executar scripts, agende a reinicialização usando uma Tarefa Agendada do Windows ou usando ferramentas como o DSC, o Chef ou extensões do Puppet.
  • Não execute um script que cause uma parada ou atualização do agente de VM. Isso poderá deixar a extensão em um estado de transição e fazer com que o tempo limite seja excedido.
  • A extensão executa um script apenas uma vez. Se você quiser executar um script em cada inicialização, use a extensão para criar uma Tarefa Agendada do Windows.
  • Se quiser agendar quando um script é executado, use a extensão para criar uma Tarefa Agendada do Windows.
  • Quando o script estiver sendo executado, você verá apenas um status da extensão em transição no portal do Azure ou na CLI do Azure. Se quiser atualizações de status mais frequentes para um script em execução, crie sua própria solução.
  • A extensão de script personalizado não dá suporte nativo a servidores proxy. No entanto, você pode usar uma ferramenta de transferência de arquivos que dê suporte a servidores proxy dentro do seu script, como a Invoke-WebRequest.
  • Esteja ciente dos locais de diretório não padrão dos quais seus scripts ou comandos poderão depender. Tenha uma lógica para lidar com essa situação.
  • A Extensão de Script Personalizado é executada no âmbito da conta do LocalSystem.
  • Se você planeja usar as propriedades storageAccountName e storageAccountKey, coloque-as em protectedSettings.
  • Você só pode ter uma versão de uma extensão aplicada à VM. Para executar um segundo script personalizado, você pode atualizar a extensão existente com uma nova configuração. Alternativamente, você pode remover a extensão de script personalizado e reaplicá-la com o script atualizado

Esquema de extensão

A configuração de extensão de script personalizado especifica itens como localização de script e o comando a ser executado. Você pode armazenar essa configuração em arquivos de configuração, especificá-la na linha de comando ou especificá-la em um modelo do Azure Resource Manager.

Você pode armazenar dados confidenciais em uma configuração protegida que é criptografada e descriptografada somente dentro da VM. A configuração protegida é útil quando o comando de execução inclui segredos como uma senha ou uma referência de arquivo SAS (assinatura de acesso compartilhado). Veja um exemplo:

{
    "apiVersion": "2018-06-01",
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "name": "virtualMachineName/config-app",
    "location": "[resourceGroup().location]",
    "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'),copyindex())]",
        "[variables('musicstoresqlName')]"
    ],
    "tags": {
        "displayName": "config-app"
    },
    "properties": {
        "publisher": "Microsoft.Compute",
        "type": "CustomScriptExtension",
        "typeHandlerVersion": "1.10",
        "autoUpgradeMinorVersion": true,
        "settings": {
            "timestamp":123456789
        },
        "protectedSettings": {
            "commandToExecute": "myExecutionCommand",
            "storageAccountName": "myStorageAccountName",
            "storageAccountKey": "myStorageAccountKey",
            "managedIdentity" : {},
            "fileUris": [
                "script location"
            ]
        }
    }
}

Observação

A propriedade managedIdentitynão pode ser usada em conjunto com a propriedade storageAccountName ou storageAccountKey.

Somente uma versão de uma extensão pode ser instalada em uma VM de cada vez. Especificar um script personalizado duas vezes no mesmo modelo do Azure Resource Manager para a mesma VM irá falhar.

Você pode usar esse esquema dentro do recurso de VM ou como um recurso autônomo. Se essa extensão for usada como um recurso autônomo no modelo do Azure Resource Manager, o nome do recurso deverá estar no formato virtualMachineName/extensionName.

Valores de propriedade

Nome Valor ou exemplo Tipo de dados
apiVersion 2015-06-15 date
publicador Microsoft.Compute string
type CustomScriptExtension string
typeHandlerVersion 1.10 INT
fileUris https://raw.githubusercontent.com/Microsoft/dotnet-core-sample-templates/master/dotnet-core-music-windows/scripts/configure-music-app.ps1 array
timestamp 123456789 Inteiro de 32 bits
commandToExecute powershell -ExecutionPolicy Unrestricted -File configure-music-app.ps1 string
storageAccountName examplestorageacct string
storageAccountKey TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg== Cadeia de caracteres
managedIdentity { } ou { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" } ou { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" } Objeto JSON

Observação

Esses nomes de propriedade diferenciam maiúsculas de minúsculas. Para evitar problemas de implantação, use os nomes conforme mostrado aqui.

Detalhes de valor de propriedade

Propriedade Opcional ou obrigatório Detalhes
fileUris Opcional URLs para arquivos a serem baixados. Se os URLs forem confidenciais, como, por exemplo, se contiverem chaves, esse campo deverá ser especificado nas protectedSettings.
commandToExecute Obrigatório O script de ponto de entrada a ser executado. Use essa propriedade se o comando contiver segredos como senhas ou se os URIs de arquivo forem confidenciais.
timestamp Opcional Altere esse valor apenas para disparar uma nova repetição do script. Qualquer valor inteiro é aceitável, desde que seja diferente do valor anterior.
storageAccountName Opcional O nome da conta de armazenamento. Se você especificar credenciais de armazenamento, todos os valores de fileUris precisarão ser URLs de blobs do Azure.
storageAccountKey Opcional A chave de acesso da conta de armazenamento.
managedIdentity Opcional A identidade gerenciada para baixar arquivos. Os valores válidos são clientId (opcional, cadeia de caracteres), que é a ID de cliente da identidade gerenciada, e objectId (opcional, cadeia de caracteres), que é a ID de objeto da identidade gerenciada.

As configurações públicas são enviadas em texto não criptografado para a VM em que o script será executado. As configurações protegidas são criptografadas por meio de uma chave conhecida apenas pelo Azure e pela VM. As configurações são salvas na VM conforme são enviadas. Ou seja, se as configurações forem criptografadas, elas serão salvas criptografadas na VM. O certificado que é usado para descriptografar os valores criptografados é armazenado na VM. O certificado também é usado para descriptografar as configurações no runtime, se necessário.

O uso de configurações públicas pode ser útil para depuração, mas recomendamos que você use as configurações protegidas.

Você pode definir os seguintes valores em configurações públicas ou protegidas. A extensão rejeita qualquer configuração em que esses valores estejam definidos em ambas as configurações, pública e protegida.

  • commandToExecute
  • fileUris

Propriedade: managedIdentity

Observação

Essa propriedade precisa ser especificada somente em configurações protegidas.

A Extensão de Script Personalizado versão, 1.10 e posterior, dá suporte a identidades gerenciadas para baixar arquivos de URLs fornecidas na configuração fileUris. A propriedade permite que a Extensão de Script Personalizado acesse os blobs ou contêineres privados do Armazenamento do Azure sem que o usuário precise transmitir segredos como tokens SAS ou chaves de conta de armazenamento.

Para usar esse recurso, o usuário precisa adicionar uma identidade atribuída pelo sistema ou atribuída pelo usuário à VM ou ao Conjunto de Dimensionamento de Máquinas Virtuais nos quais a Extensão de Script Personalizado é executada. A seguir, conceda o acesso de identidade gerenciada ao contêiner ou blob de Armazenamento do Azure.

Para usar a identidade atribuída pelo sistema na VM ou no Conjunto de Dimensionamento de Máquinas Virtuais de destino, defina managedidentity como um objeto JSON vazio.

{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : {}
}

Para usar a identidade atribuída pelo usuário na VM ou no Conjunto de Dimensionamento de Máquinas Virtuais de destino, configure managedidentity com a ID de cliente ou a ID de objeto da identidade gerenciada.

{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" }
}
{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" }
}

Observação

A propriedade managedIdentitynão pode ser usada em conjunto com a propriedade storageAccountName ou storageAccountKey.

Implantação de modelo

É possível implantar extensões de VM do Azure com os modelos do Azure Resource Manager. O esquema JSON detalhado na seção anterior pode ser usado em um modelo do Azure Resource Manager para executar a extensão de script personalizado durante a implantação do modelo. Os seguintes exemplos mostram como usar a extensão de script personalizado:

Implantação do PowerShell

Você pode usar o comando Set-AzVMCustomScriptExtension para adicionar a extensão de script personalizado a uma máquina virtual existente. Para obter mais informações, confira Set-AzVMCustomScriptExtension.

Set-AzVMCustomScriptExtension -ResourceGroupName <resourceGroupName> `
    -VMName <vmName> `
    -Location myLocation `
    -FileUri <fileUrl> `
    -Run 'myScript.ps1' `
    -Name DemoScriptExtension

Exemplos

Usando vários scripts

Esse exemplo usa três scripts para criar seu servidor. A propriedade commandToExecute chama o primeiro script. Depois, há opções para chamar os outros. Por exemplo, você pode ter um script principal que controla a execução, com o tratamento de erro, o registro em log e o gerenciamento de estado corretos. Os scripts são baixados no computador local para serem executados.

Por exemplo, em 1_Add_Tools.ps1, você chamaria 2_Add_Features.ps1 adicionando .\2_Add_Features.ps1 ao script. Repita esse processo para os outros scripts que você definir em $settings.

$fileUri = @("https://xxxxxxx.blob.core.windows.net/buildServer1/1_Add_Tools.ps1",
"https://xxxxxxx.blob.core.windows.net/buildServer1/2_Add_Features.ps1",
"https://xxxxxxx.blob.core.windows.net/buildServer1/3_CompleteInstall.ps1")

$settings = @{"fileUris" = $fileUri};

$storageAcctName = "xxxxxxx"
$storageKey = "1234ABCD"
$protectedSettings = @{"storageAccountName" = $storageAcctName; "storageAccountKey" = $storageKey; "commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File 1_Add_Tools.ps1"};

#run command
Set-AzVMExtension -ResourceGroupName <resourceGroupName> `
    -Location <locationName> `
    -VMName <vmName> `
    -Name "buildserver1" `
    -Publisher "Microsoft.Compute" `
    -ExtensionType "CustomScriptExtension" `
    -TypeHandlerVersion "1.10" `
    -Settings $settings `
    -ProtectedSettings $protectedSettings;

Executando scripts de um compartilhamento local

Neste exemplo, você poderia usar um servidor local do protocolo SMB como local do script. Depois, você não precisará fornecer outras configurações, exceto commandToExecute.

$protectedSettings = @{"commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File \\filesvr\build\serverUpdate1.ps1"};

Set-AzVMExtension -ResourceGroupName <resourceGroupName> `
    -Location <locationName> `
    -VMName <vmName> `
    -Name "serverUpdate"
    -Publisher "Microsoft.Compute" `
    -ExtensionType "CustomScriptExtension" `
    -TypeHandlerVersion "1.10" `
    -ProtectedSettings $protectedSettings

Como executar um script personalizado mais de uma vez usando a CLI

O manipulador da Extensão de Script Personalizado impedirá uma nova execução de um script se as exatamente as mesmas configurações forem transmitidas. Esse comportamento impede a nova execução acidental, o que poderá causar comportamentos inesperados se o script não for idempotente. Para confirmar se o manipulador bloqueou a execução novamente, verifique emC:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension\<HandlerVersion>\CustomScriptHandler.log*. Procure um aviso parecido com esse:

Current sequence number, <SequenceNumber>, is not greater than the sequence number
of the most recently executed configuration. Exiting...

Se você quiser executar a extensão de script personalizado mais de uma vez, faça isso somente sob estas condições:

  • O parâmetro da extensão Name é o mesmo que o da implantação anterior da extensão.
  • Você atualizou a configuração. Você pode adicionar uma propriedade dinâmica ao comando, como um carimbo de data/hora. Se detectar uma alteração nas definições de configuração, o manipulador vai interpretar essa alteração como um desejo explícito de executar o script novamente.

Como alternativa, você pode definir a propriedade ForceUpdateTag como true.

Como usar Invoke-WebRequest

Se você estiver usando Invoke-WebRequest no script, especifique o parâmetro -UseBasicParsing. Se não especificar o parâmetro, você obterá o seguinte erro ao verificar o status detalhado:

The response content cannot be parsed because the Internet Explorer engine
is not available, or Internet Explorer's first-launch configuration
is not complete. Specify the UseBasicParsing parameter and try again.

Conjuntos de Dimensionamento de Máquinas Virtuais

Se você implantar a extensão de script personalizado usando o portal do Azure, não terá controle sobre a expiração do token SAS para acessar o script na conta de armazenamento. A implantação inicial funciona, mas quando o token SAS da conta de armazenamento expirar, as próximas operações de dimensionamento irão falhar porque a Extensão de Script Personalizado não poderá mais acessar a conta de armazenamento.

Recomendamos que você use o PowerShell, a CLI do Azure ou um modelo do Azure Resource Manager ao implantar a Extensão de Script Personalizado em um Conjunto de Dimensionamento de Máquinas Virtuais. Assim, você pode usar uma identidade gerenciada ou ter controle direto da expiração do token SAS para acessar o script na conta de armazenamento durante o tempo que for necessário.

Solução de problemas e suporte

Você pode recuperar dados sobre o estado das implantações de extensão por meio do portal do Azure e do módulo do Azure PowerShell. Para ver o estado de implantação das extensões de uma VM, execute o seguinte comando:

Get-AzVMExtension -ResourceGroupName <resourceGroupName> `
    -VMName <vmName> -Name myExtensionName

A saída da extensão é registrada nos arquivos localizados na seguinte pasta, na máquina virtual de destino:

C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension

Os arquivos especificados são baixados na seguinte pasta, na máquina virtual de destino:

C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.*\Downloads\<n>

No caminho anterior, <n> é um inteiro decimal que pode ser alterado entre as execuções da extensão. O valor 1.* corresponde ao valor typeHandlerVersion atual e real da extensão. Por exemplo, o diretório real pode ser C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2.

Quando você executa o comando commandToExecute, a extensão define esse diretório, como, por exemplo, ...\Downloads\2, como o diretório de trabalho atual. Esse processo permite o uso de caminhos relativos para localizar os arquivos baixados usando a propriedade fileURIs. Aqui estão exemplos de arquivos baixados:

URI em fileUris Local de download relativo Local de download absoluto
https://someAcct.blob.core.windows.net/aContainer/scripts/myscript.ps1 ./scripts/myscript.ps1 C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2\scripts\myscript.ps1
https://someAcct.blob.core.windows.net/aContainer/topLevel.ps1 ./topLevel.ps1 C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2\topLevel.ps1

Os caminhos de diretório absolutos mudam ao longo do tempo de vida da VM, mas não dentro de uma única execução da Extensão de Script Personalizado.

Como o caminho de download absoluto pode variar ao longo do tempo, é melhor optar por caminhos relativos de script/arquivo na cadeia de caracteres commandToExecute, sempre que possível. Por exemplo:

"commandToExecute": "powershell.exe . . . -File \"./scripts/myscript.ps1\""

As informações de caminho após o primeiro segmento do URI são retidas para os arquivos baixados usando a lista de propriedades fileUris. Conforme mostrado na tabela anterior, os arquivos baixados são mapeados em subdiretórios de download para refletir a estrutura dos valores de fileUris.

Suporte