Compartilhar via


Depurar scripts do PowerShell executados pela Extensão de Script Personalizado ou Executar Comando

Aplica-se a: ✔️ VMs do Windows

Este artigo discute como testar e corrigir uma falha em um script do PowerShell que usa a Extensão de Script Personalizado ou o recurso Executar Comando.

Pré-requisitos

Visão geral

Suponha que você tenha usado o recurso Extensão de Script Personalizado ou Executar Comando para executar um script do PowerShell. O que você faz se o script falhar? Você tem vários métodos disponíveis para determinar a causa da falha.

O PowerShell tem mais de um fluxo de saída. Os logs dos scripts de Extensão de Script Personalizado e Executar Comando enviam o fluxo de Êxito para o StdOut substatus e o fluxo de Erro para o StdErr substatus. Esses substatus pertencem à extensão que foi usada para executar o script de Extensão de Script Personalizado ou o script Executar Comando.

Os StdOut substatus e StdErr estão na exibição da instância do CRP (ponto de registro de certificado) da VM (máquina virtual). Esses substatus são visíveis em vários locais, de acordo com a tabela a seguir.

Interface Como visualizar o substatus
Portal do Azure
  1. Pesquise por Máquinas virtuais e selecione essa opção.
  2. Selecione a VM na lista.
  3. Na página de visão geral da VM, selecione Extensões + Extensões de aplicativos>.
  4. Selecione a extensão que foi usada para executar o comando. (Ele será nomeado ou CustomScriptExtension ou RunCommand.)
  5. Selecione Exibir status detalhado.
Azure PowerShell Insira o cmdlet Get-AzVM para obter as propriedades de uma VM do Azure, da seguinte maneira:
Get-AzVM -ResourceGroupName <resource-group-name> -Name <vm-name> -Status
CLI do Azure Insira o comando az vm get-instance-view para obter informações de instância sobre uma VM do Azure, da seguinte maneira:
az vm get-instance-view --resource-group <resource-group-name> --name <vm-name> --query instanceView.extensions

O erro que geralmente faz com que o script falhe aparece no StdErr substatus. No entanto, os scripts também podem falhar sem registrar uma entrada de erro fatal nesse substatus.

Testar o script manualmente e usando PsExec

Verifique manualmente se o script é executado com êxito em um console administrativo do PowerShell na VM.

Se o script funcionar manualmente, use PsExec para executar o script usando a conta do sistema local. Para a Extensão de Script Personalizado e o Comando de Execução, os scripts são executados usando essa conta. Ao inserir psexec -s, você pode testar o script usando a conta do sistema local, mas sem usar a Extensão de Script Personalizado ou o Comando Executar. Se a falha for reproduzida usando psexec -s, a Extensão de Script Personalizado e o Comando Executar não serão a causa do problema.

Testar usando PsExec

Você pode usar o PsExec para executar um script de teste do PowerShell remotamente. Abra uma janela administrativa do Prompt de Comando e insira o seguinte comando PsExec. Substitua o espaço reservado pelo nome totalmente qualificado do script do PowerShell:

psexec -accepteula -nobanner -s powershell.exe -NoLogo -NoProfile -File <C:\path\script-name.ps1>

Ou você pode usar o PsExec interativamente. No exemplo a seguir, você insere o comando whoami para mostrar que o PowerShell está em execução na conta do Sistema Local (NT AUTHORITY\SYSTEM):

C:\>psexec -accepteula -nobanner -s powershell.exe -NoLogo -NoProfile

PS C:\Windows\system32> whoami
nt authority\system 

Ativar o registro em log da execução de script do PowerShell

Se o StdErr substatus não mostrar a causa do problema, você poderá ativar vários tipos de registro em log para mostrar coletivamente o conteúdo e a saída do script. Esse registro mostra o que o script está tentando realizar e o resultado da execução do script.

Para ativar diferentes tipos de registro em log, siga as etapas nas próximas seções.

Aviso

Algumas das instruções envolvem a alteração do registro do Windows. Poderão ocorrer sérios problemas se você modificar o Registro incorretamente com o Editor do Registro ou outro método. Talvez seja necessária a reinstalação do sistema operacional. A Microsoft não garante que esses problemas possam ser solucionados. Faça backup de suas entradas de registro existentes primeiro e, em seguida, modifique o registro por sua conta e risco.

Aumentar o tamanho máximo dos logs de eventos

Um grande número de eventos pode ser gerado no log de segurança e no log de eventos Microsoft-Windows-PowerShell/Operacional. Para evitar a perda desses eventos registrados, aumente o tamanho máximo dos logs. Mas se um desses logs estiver no tamanho máximo de 100 MB ou maior (um maxSize valor de 104.857.600 ou mais), deixe a configuração de tamanho máximo como está.

Para verificar o tamanho máximo do log, use o comando wevtutil e a get-log opção de recuperar informações sobre logs de eventos:

wevtutil get-log "Security"
wevtutil get-log "Microsoft-Windows-PowerShell/Operational"

Você verá uma saída semelhante ao texto a seguir. Nesses casos, o tamanho máximo do log é muito menor que 100 MB.

name: Security
enabled: true
type: Admin
owningPublisher:
isolation: Custom
channelAccess: O:BAG:SYD:(A;;CCLCSDRCWDWO;;;SY)(A;;CCLC;;;BA)(A;;CC;;;ER)(A;;CC;;;NS)
logging:
  logFileName: %SystemRoot%\System32\Winevt\Logs\Security.evtx
  retention: false
  autoBackup: false
  maxSize: 20971520
publishing:
  fileMax: 1
name: Microsoft-Windows-PowerShell/Operational
enabled: true
type: Operational
owningPublisher: Microsoft-Windows-PowerShell
isolation: Application
channelAccess: O:BAG:SYD:(A;;0x2;;;S-1-15-2-1)(A;;0x2;;;S-1-15-3-1024-3153509613-960666767-3724611135-2725662640-12138253-543910227-1950414635-4190290187)(A;;0xf0007;;;SY)(A;;0x7;;;BA)(A;;0x7;;;SO)(A;;0x3;;;IU)(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)(A;;0x3;;;S-1-5-33)(A;;0x1;;;S-1-5-32-573)
logging:
  logFileName: %SystemRoot%\System32\Winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx
  retention: false
  autoBackup: false
  maxSize: 15728640
publishing:
  fileMax: 1

Para aumentar o tamanho máximo do log de segurança ou do log de eventos Microsoft-Windows-PowerShell/Operational para 100 MB, execute wevtutil junto com a set-log opção:

wevtutil set-log "Security" /ms:104857600
wevtutil set-log "Microsoft-Windows-PowerShell/Operational" /ms:104857600

Ativar a auditoria de criação de processos

Use o seguinte comando para ativar a auditoria de criação de processos:

reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v "ProcessCreationIncludeCmdLine_Enabled" /t REG_DWORD /d 1 /f

Ativar a transcrição do PowerShell

reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\Transcription" /v "EnableTranscripting" /t REG_DWORD /d 1 /f
reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\Transcription" /v "EnableInvocationHeader" /t REG_DWORD /d 1 /f
reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\Transcription" /v "OutputDirectory" /t REG_SZ /d C:\Transcripts /f

Ativar o log do módulo do PowerShell

reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging" /v "EnableModuleLogging" /t REG_DWORD /d 1 /f
reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames" /v "*" /t REG_SZ /d *

Ativar o log de blocos de script do PowerShell

reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v "EnableScriptBlockLogging" /t REG_DWORD /d 1 /f

Como entender a saída

A auditoria da criação do processo gravará a ID do Evento 4688 e a ID do Evento 4689 no log de eventos de segurança. A ID do evento 4688 é para a criação do processo e inclui a Linha de Comando do Processo. A ID do evento 4689 é para o encerramento do processo.

A transcrição cria um arquivo de texto no diretório C:\Transcripts\<output-date> . O diretório será criado automaticamente se ainda não existir.

Por exemplo:

C:\transcrições\20201211\PowerShell_transcript.<nome> da vm.a+BWp8CT.20201211034929.txt

O log do módulo registrará a ID do evento 4103 no log de eventos Microsoft-Windows-PowerShell/Operacional. O evento "4103" inclui o nome e a saída do cmdlet.

Se você executar Write-Host $Env:ComputerNameo , a parte superior da ID do evento 4013 mostrará o seguinte texto, onde value="<vm-name>" indica que a saída do comando foi o nome da VM:

CommandInvocation(Write-Host): "Write-Host"
ParameterBinding(Write-Host): name="Object"; value="<vm-name>"

O log de blocos de script registrará a ID do evento 4104 no log de eventos Microsoft-Windows-PowerShell/Operacional . Os eventos "4104" contêm o conteúdo do script. Os scripts que excedem o tamanho máximo da mensagem de um evento são registrados como vários eventos "4104".

Depois de ativar o log e reproduzir a falha do script, execute o script a seguir para exportar os eventos relevantes para um arquivo CSV (valores separados por vírgula). A consulta a seguir examina as 24 horas anteriores (86.400.000 milissegundos) de dados. Insira o valor 3600000 para recuperar apenas a hora mais recente. O valor 604800000 recuperará a semana mais recente.

$path = "PSEvents_$($env:COMPUTERNAME)_$(Get-Date ((Get-Date).ToUniversalTime()) -Format yyyyMMddHHmmss).csv"

$hours = 1 # Increase this to have it query more than just the last 1 hour
$now = Get-Date
$startTimeUtc = Get-Date ($now.AddHours(-$hours).ToUniversalTime()) -Format 'yyyy-MM-ddTHH:mm:ssZ'
$endTimeUtc = Get-Date ($now.ToUniversalTime()) -Format 'yyyy-MM-ddTHH:mm:ssZ'

$filterXML = @"
<QueryList>
    <Query Id="0" Path="Security">
        <Select Path="Security">
            Event
            [
                System
                [
                    (EventID = '4688' or EventID = '4689')
                    and
                    TimeCreated
                    [
                        @SystemTime &gt;= '$startTimeUtc'
                        and
                        @SystemTime &lt;= '$endTimeUtc'
                    ]
                ]
                and
                EventData
                [
                    Data[@Name="SubjectUserSid"] = "S-1-5-18"
                ]
            ]
        </Select>
    </Query>
    <Query Id="1" Path="Microsoft-Windows-PowerShell/Operational">
        <Select Path="Microsoft-Windows-PowerShell/Operational">
            Event
            [
                System
                [
                    (EventID ='4103' or EventID ='4104')
                    and
                    Security
                    [
                        @UserID ='S-1-5-18'
                    ]
                    and
                    TimeCreated
                    [
                        @SystemTime &gt;= '$startTimeUtc'
                        and
                        @SystemTime &lt;= '$endTimeUtc'
                    ]
                ]
            ]
        </Select>
    </Query>
</QueryList>
"@

$events = Get-WinEvent -FilterXml $filterXML | Sort-Object -Property RecordId
$events = $events | Select-Object -Property RecordId,
    TimeCreated, Id, MachineName, LogName, TaskDisplayName, Message
$events | Export-Csv -Path $path -NoTypeInformation

Desativar o registro em log da execução de script do PowerShell

Para desfazer as alterações feitas para habilitar o registro em log de scripts do PowerShell em sua VM, execute as seguintes etapas:

  1. Se você aumentou anteriormente o tamanho máximo do log de segurança ou do log Microsoft-Windows-PowerShell/Operacional, reverta esses valores para os tamanhos máximos padrão:

    wevtutil set-log "Security" /ms:20971520
    wevtutil set-log "Microsoft-Windows-PowerShell/Operational" /ms:15728640
    
  2. Desative a auditoria de criação de processos:

    reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v "ProcessCreationIncludeCmdLine_Enabled" /t REG_DWORD /d 0 /f
    
  3. Desative a transcrição:

    reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" /v "EnableTranscripting" /t REG_DWORD /d 0 /f
    reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" /v "EnableInvocationHeader" /t REG_DWORD /d 0 /f
    reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" /v "OutputDirectory"
    
  4. Desative o registro do módulo:

    reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging" /v "EnableModuleLogging" /t REG_DWORD /d 0 /f
    reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames" /v "*"
    
  5. Desative o registro de blocos de script:

    reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v "EnableScriptBlockLogging" /t REG_DWORD /d 0 /f
    
  6. Remova a pasta de transcrição:

    Remove-Item -Path 'C:\Transcripts' -Force -Recurse
    
  7. Faça backup e limpe o log de segurança e o log Microsoft-Windows-PowerShell/Operacional:

    wevtutil clear-log Security /bu:Security.evtx
    wevtutil clear-log Microsoft-Windows-PowerShell/Operational /bu:Microsoft-Windows-PowerShell_Operational.evtx
    

    Ou limpe o log de segurança e o log Microsoft-Windows-PowerShell/Operacional sem fazer backup deles:

    wevtutil clear-log Security
    wevtutil clear-log Microsoft-Windows-PowerShell/Operational
    

Log do Comando de Execução de Teste em sua VM

Baixe o script de teste Test-CustomScriptExtension.ps1 para o diretório local atual. Em seguida, execute o script em sua VM usando o cmdlet Invoke-AzVMRunCommand . Use as propriedades da VM para substituir os espaços reservados para o nome do grupo de recursos e o nome da VM.

$scriptUri = 'https://raw.githubusercontent.com/Azure/azure-support-scripts/blob/users/GitHubPolicyService/6294a303-e34d-4bad-b6cd-5ed54245f020/Images_Extensions/PowerShell/Test-CustomScriptExtension.ps1'
$localFileLocation = "$PWD\Test-CustomScriptExtension.ps1"
(New-Object System.Net.WebClient).DownloadFile($scriptUri, $localFileLocation)

$commandSettings = @{
    ResourceGroupName = '<resource-group-name>'
    VMName = '<vm-name>'
    CommandId = 'RunPowerShellScript'
    ScriptPath = $localFileLocation
}
Invoke-AzVMRunCommand @commandSettings

Testar o log da Extensão de Script Personalizado em sua VM

Execute o script de teste Test-CustomScriptExtension.ps1 em sua VM usando o cmdlet Set-AzVMCustomScriptExtension . Use as propriedades da VM para substituir os espaços reservados para o nome do grupo de recursos, o nome da VM e o local.

$commandSettings = @{
    ResourceGroupName = '<resource-group-name>'
    VMName = '<vm-name>'
    Name = 'CustomScriptExtension'
    FileUri = 'https://raw.githubusercontent.com/Azure/azure-support-scripts/blob/users/GitHubPolicyService/6294a303-e34d-4bad-b6cd-5ed54245f020/Images_Extensions/PowerShell/Test-CustomScriptExtension.ps1'
    Run = 'Test-CustomScriptExtension.ps1'
    Location = '<azure-region-name-or-code>'
    ForceRerun = (Get-Date).Ticks
}
Set-AzVMCustomScriptExtension @commandSettings

Como alternativa, você pode executar esse script de teste em sua VM usando o cmdlet Set-AzVMExtension . Você terá que especificar um ExtensionType parâmetro de junto com várias outras alterações de CustomScriptExtension parâmetro. Use as propriedades da VM para substituir os espaços reservados para o nome do grupo de recursos, o nome da VM e o local.

$publicConfigSettings = @{
    'fileUris' = @('https://raw.githubusercontent.com/Azure/azure-support-scripts/blob/users/GitHubPolicyService/6294a303-e34d-4bad-b6cd-5ed54245f020/Images_Extensions/PowerShell/Test-CustomScriptExtension.ps1')
    'commandToExecute' = 'powershell -File Test-CustomScriptExtension.ps1 -ExecutionPolicy Unrestricted'
}
$commandSettings = @{
    Publisher = 'Microsoft.Compute'
    ExtensionType = 'CustomScriptExtension'
    Settings = $publicConfigSettings
    ResourceGroupName = '<resource-group-name>'
    VMName = '<vm-name>'
    Name = 'CustomScriptExtension'
    TypeHandlerVersion = '1.10'
    Location = '<azure-region-name-or-code>'
}
Set-AzVMExtension @commandSettings

Erros comuns no script de teste da Extensão de Script Personalizado

  • Código de saída diferente de zero: depois de executar o script Test-CustomScriptExtension.ps1 , espere receber a seguinte mensagem de erro:

    Falha na operação de execução longa com o status 'Falha'.
    Informações adicionais: a VM relatou uma falha ao processar a extensão 'CustomScriptExtension'.
    Mensagem de erro: "A execução do comando foi concluída, mas falhou porque retornou um código de saída diferente de zero de: '2'"

    O script de teste executa o Exit 2 comando e espera-se que a Extensão de Script Personalizado falhe por design se o script retornar um código de saída diferente de zero. (Neste exemplo, 2 é o código de saída diferente de zero.) Este exemplo mostra como uma falha aparece no log extra do PowerShell que você habilitou.

  • A alteração está em conflito: esse erro indica que a VM já tem a Extensão de Script Personalizado instalada como nome de recurso Microsoft.Compute.CustomScriptExtension, mas você está especificando um nome de recurso diferente de CustomScriptExtension para sua execução atual:

    Não é possível atualizar handlerVersion ou autoUpgradeMinorVersion para a extensão de VM 'CustomScriptExtension'.
    A alteração está em conflito com outras extensões no manipulador 'Microsoft.Compute.CustomScriptExtension', com typeHandler versão '1.10' e autoUpgradeMinorVersion 'True'.
    Código de erro: OperationNotAllowed
    ErrorMessage: não é possível atualizar handlerVersion ou autoUpgradeMinorVersion para a extensão de VM 'CustomScriptExtension'.
    A alteração está em conflito com outras extensões no manipulador 'Microsoft.Compute.CustomScriptExtension', com typeHandler versão '1.10' e autoUpgradeMinorVersion 'True'.
    Alvo de erro:
    Código de status: 409
    ReasonPhrase: Conflito

    Você pode especificar o que quiser para o nome do recurso. No entanto, se você já tiver a Extensão de Script Personalizado instalada, deverá executar uma das seguintes ações:

    • Use o mesmo nome para execuções subsequentes.
    • Primeiro, remova esse recurso de extensão antes de usar um nome de recurso diferente.
  • Configuração de URI de arquivo inválida: esse erro indica que a Extensão de Script Personalizado foi originalmente instalada junto com URIs de arquivo especificados em configurações protegidas, mas agora são especificados em configurações públicas (ou vice-versa):

    Falha na operação de execução longa com o status 'Falha'.
    Informações adicionais: a VM relatou uma falha ao processar a extensão 'CustomScriptExtension'.
    Mensagem de erro: "Configuração inválida - FileUris está presente nas seções de configuração protegida e pública; deve ser especificado em apenas uma seção.

Soluções para erros comuns no script de teste da Extensão de Script Personalizado

  • Para corrigir o erro "A alteração está em conflito", tente executar Set-AzVMCustomScriptExtension novamente ou Set-AzVMExtension, mas defina o -Name parâmetro como o nome do recurso de Extensão de Script Personalizado que já está instalado na VM. Para o erro de exemplo, ao remover a extensão, especifique um -Name parâmetro de Microsoft.Compute.CustomScriptExtension. Mas o -Name parâmetro deve ser qualquer que seja o nome do recurso para o recurso de extensão que já está instalado na VM.

    O nome a ser usado será -Name o nome do recurso nesta parte do erro: "A alteração está em conflito com outras extensões no manipulador '<resource-name>'."

    Você também pode verificar o nome correto do recurso a ser usado obtendo-o do status da VM. Insira o cmdlet Get-AzVM da seguinte maneira:

    $status = Get-AzVM -ResourceGroupName <resource-group> -Name <vm-name> -Status
    $status.Extensions |
    Where-Object Type -EQ 'Microsoft.Compute.CustomScriptExtension' |
    Select-Object Name
    
  • Para atenuar o erro "A alteração está em conflito" e o erro "FileUris", você pode remover a extensão de script personalizado existente inserindo o cmdlet Remove-AzVMCustomScriptExtension :

    $params = @{
        ResourceGroupName = '<resourceGroupName>'
        VMName = '<vm-name>'
        Name = '<extension-resource-name>'
        Force = $True
    }
    Remove-AzVMCustomScriptExtension @params
    

    Se você especificar o nome do recurso incorreto, o valor retornado StatusCode será NoContent:

    RequestId IsSuccessStatusCode StatusCode ReasonPhrase
    --------- ------------------- ---------- ------------
                             True  NoContent No Content
    

    Se você especificar o nome correto do recurso, o valor retornado StatusCode será OK:

    RequestId IsSuccessStatusCode StatusCode ReasonPhrase
    --------- ------------------- ---------- ------------
                             True         OK OK
    

Referências

Entre em contato conosco para obter ajuda

Se você tiver dúvidas ou precisar de ajuda, crie uma solicitação de suporte ou peça ajuda à comunidade de suporte do Azure. Você também pode enviar comentários sobre o produto para a comunidade de comentários do Azure.

Aviso de isenção de responsabilidade para contatos de terceiros

A Microsoft fornece informações de contato de terceiros para ajudá-lo a encontrar informações adicionais sobre esse tópico. Essas informações de contato podem ser alteradas sem aviso prévio. A Microsoft não garante a precisão das informações de contato de terceiros.