カスタム スクリプト拡張機能または実行コマンドによって実行される PowerShell スクリプトをデバッグする

適用対象: ✔️ Windows VM

まとめ

この記事では、カスタム スクリプト拡張機能またはコマンド実行機能を使用する PowerShell スクリプトでエラーをテストして修正する方法について説明します。

Important

New! VM の支援を試して、上位の問題を解決してください。 Windows の場合は VM assist、LinuxVM assist を実行することをお勧めします>。 これらのスクリプト ベースの診断ツールは、Azure VM ゲスト エージェントと VM の全体的な正常性に影響する一般的な問題を特定するのに役立ちます。

VM でパフォーマンスの問題が発生している場合は、まずこれらのツールを実行してから、Microsoft サポートにお問い合わせください。

前提条件

概要

Custom スクリプト拡張機能または Run Command 機能を使用して PowerShell スクリプトを実行したとします。 スクリプトが失敗した場合の処理 エラーの原因を特定するには、いくつかの方法があります。

PowerShell には複数の出力ストリームがあります。 カスタム スクリプト拡張機能スクリプトと実行コマンド スクリプトのログは、 Success ストリームを StdOut サブステータスに、 Error ストリームを StdErr サブステータスに送信します。 これらのサブステータスは、カスタム スクリプト拡張機能スクリプトまたはコマンド実行スクリプトを実行するために使用された拡張機能に属します。

StdOutStdErrのサブステータスは、仮想マシン (VM) の証明書登録ポイント (CRP) インスタンス ビューにあります。 これらの副状態は、次の表に示すように、複数の場所に表示されます。

インターフェース 副状態を表示する方法
Azure portal
  1. [仮想マシン] を検索して選択します。
  2. 一覧で VM を選択します。
  3. VM の概要ページで、 Extensions + applications>Extensions を選択します。
  4. コマンドの実行に使用された拡張機能を選択します。 ( のいずれかの名前が付けられますCustomScriptExtension または RunCommand.)
  5. 詳細な状態を表示を選択
Azure PowerShell 次のように、Get-AzVM コマンドレットを入力して、Azure VM のプロパティを取得します。
Get-AzVM -ResourceGroupName <resource-group-name> -Name <vm-name> -Status
Azure CLI 次のように、az vm get-instance-view コマンドを入力して、Azure VM に関するインスタンス情報を取得します。
az vm get-instance-view --resource-group <resource-group-name> --name <vm-name> --query instanceView.extensions

通常、スクリプトが失敗する原因となるエラーは、 StdErr の副状態に表示されます。 ただし、スクリプトは、そのサブステータスに致命的なエラー エントリを記録せずに失敗する場合もあります。

PsExec を使用して手動でスクリプトをテストする

VM 上の管理 PowerShell コンソールからスクリプトが正常に実行されていることを手動で確認します。

スクリプトが手動で動作する場合は、PsExec を使用して、ローカル システム アカウントを使用してスクリプトを実行します。 カスタム スクリプト拡張機能と実行コマンドの両方で、そのアカウントを使用してスクリプトが実行されます。 psexec -s入力すると、ローカル システム アカウントを使用してスクリプトをテストできますが、カスタム スクリプト拡張機能または実行コマンドは使用しません。 psexec -sを使用してエラーが再現された場合、カスタム スクリプト拡張機能と実行コマンドは問題の原因ではありません。

PsExec を使用してテストする

PsExec を使用して、PowerShell テスト スクリプトをリモートで実行できます。 管理コマンド プロンプト ウィンドウを開き、次の PsExec コマンドを入力します。 プレースホルダーを PowerShell スクリプトの完全修飾名に置き換えます。

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

または、PsExec を対話形式で使用することもできます。 次の例では、 whoami コマンドを入力して、PowerShell がローカル システム (NT AUTHORITY\SYSTEM) アカウントで実行されていることを示します。

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

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

PowerShell スクリプトの実行のログ記録を有効にする

StdErrの副状態に問題の原因が表示されない場合は、いくつかの種類のログ記録を有効にして、スクリプトの内容と出力をまとめて表示できます。 このログは、スクリプトが実行しようとしている内容と、スクリプトを実行した結果を示しています。

さまざまな種類のログ記録を有効にするには、次のいくつかのセクションの手順に従います。

警告

手順の一部には、Windows レジストリの変更が含まれます。 レジストリ エディタや他の方法を使用してレジストリを変更する際、適切に変更しないと重大な問題を引き起こす可能性があります。 場合によっては、オペレーティング システムの再インストールが必要になります。 Microsoftこれらの問題を解決できることを保証することはできません。 まず、既存のレジストリ エントリをバックアップしてから 自分の責任でレジストリを変更します。

イベント ログの最大サイズを増やす

セキュリティ ログと Microsoft-Windows-PowerShell/Operational イベント ログの両方で多数のイベントを生成できます。 ログに記録されたこれらのイベントが失われるのを防ぐには、ログの最大サイズを増やします。 ただし、これらのログのいずれかが最大サイズ 100 MB 以上 ( maxSize 値が 104,857,600 以上) の場合は、最大サイズの設定をそのままにします。

ログの最大サイズを確認するには、 wevtutil コマンドと get-log オプションを使用して、イベント ログに関する情報を取得します。

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

次のテキストのような出力が表示されます。 このような場合、ログの最大サイズは 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

セキュリティ ログまたは Microsoft-Windows-PowerShell/Operational イベント ログの最大サイズを 100 MB に増やすには、wevtutil オプションと共に set-log を実行します。

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

プロセス作成の監査を有効にする

次のコマンドを使用して、プロセス作成の監査を有効にします。

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

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

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 *

PowerShell スクリプト ブロックのログ記録を有効にする

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

出力を理解する

プロセス作成の監査により、 Event ID 4688Event ID 4689 がセキュリティ イベント ログに書き込まれます。 イベント ID 4688 はプロセスの作成用であり、プロセス コマンド ラインが含まれています。 イベント ID 4689 はプロセス終了用です。

文字起こしは、 C:\Transcripts\<output-date> ディレクトリにテキスト ファイルを作成します。 ディレクトリがまだ存在しない場合は、自動的に作成されます。

例えば次が挙げられます。

C:\transcripts\20201211\PowerShell_transcript.<vm-name>.a+BWp8CT.20201211034929.txt

モジュール ログでは、イベント ID 4103 が Microsoft-Windows-PowerShell/Operational イベント ログに記録されます。 "4103" イベントには、コマンドレットの名前と出力が含まれています。

Write-Host $Env:ComputerNameを実行すると、イベント ID 4013 の先頭に次のテキストが表示されます。value="<vm-name>"は、コマンドの出力が VM の名前であることを示します。

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

スクリプト ブロックのログ記録では、イベント ID 4104 が Microsoft-Windows-PowerShell/Operational イベント ログに記録されます。 "4104" イベントには、スクリプトの内容が含まれています。 イベントの最大メッセージ サイズを超えるスクリプトは、複数の "4104" イベントとしてログに記録されます。

ログ記録を有効にしてスクリプトエラーを再現したら、次のスクリプトを実行して、関連するイベントをコンマ区切り値 (CSV) ファイルにエクスポートします。 次のクエリでは、過去 24 時間 (86,400,000 ミリ秒) のデータを調べます。 最新の時間のみを取得するには、 3600000 値を入力します。 値 6048000000 は最新の週を取得します。

$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

PowerShell スクリプトの実行のログ記録を無効にする

VM で PowerShell スクリプトのログ記録を有効にするために行った変更を元に戻すには、次の手順を実行します。

  1. 以前にセキュリティ ログまたは Microsoft-Windows-PowerShell/Operational ログの最大サイズを増やした場合は、これらの値を既定の最大サイズに戻します。

    wevtutil set-log "Security" /ms:20971520
    wevtutil set-log "Microsoft-Windows-PowerShell/Operational" /ms:15728640
    
  2. プロセス作成の監査をオフにします。

    reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v "ProcessCreationIncludeCmdLine_Enabled" /t REG_DWORD /d 0 /f
    
  3. 文字起こしをオフにします。

    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. モジュールのログ記録をオフにする:

    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. スクリプト ブロックのログ記録をオフにします。

    reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v "EnableScriptBlockLogging" /t REG_DWORD /d 0 /f
    
  6. 文字起こしフォルダーを削除します。

    Remove-Item -Path 'C:\Transcripts' -Force -Recurse
    
  7. セキュリティ ログと Microsoft-Windows-PowerShell/運用ログをバックアップしてクリアします。

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

    または、セキュリティ ログと Microsoft-Windows-PowerShell/Operational ログをバックアップせずにクリアします。

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

VM でのコマンド ログのテスト実行

Test-CustomScriptExtension.ps1テスト スクリプトを現在のローカル ディレクトリにダウンロードします。 次に、 Invoke-AzVMRunCommand コマンドレットを使用して、VM でスクリプトを実行します。 VM のプロパティを使用して、リソース グループ名と 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

VM でカスタム スクリプト拡張機能のログ記録をテストする

Set-AzVMCustomScriptExtension> コマンドレットを使用して、VM でテスト スクリプト Test-CustomScriptExtension.ps1 を実行します。 VM のプロパティを使用して、リソース グループ名、VM 名、場所のプレースホルダーを置き換えます。

$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

または、 Set-AzVMExtension コマンドレットを使用して、VM でテスト スクリプトを実行することもできます。 ExtensionTypeCustomScriptExtension パラメーターを、他のいくつかのパラメーター変更と共に指定する必要があります。 VM のプロパティを使用して、リソース グループ名、VM 名、場所のプレースホルダーを置き換えます。

$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

カスタム スクリプト拡張機能テスト スクリプトの一般的なエラー

  • 0 以外の終了コード: Test-CustomScriptExtension.ps1 スクリプトを実行すると、次のエラー メッセージが表示されます。

    長時間実行操作が状態 '失敗' で失敗しました。
    追加情報: 拡張機能 'CustomScriptExtension' の処理中に VM からエラーが報告されました。
    エラー メッセージ: "コマンドの実行は完了しましたが、'2' の 0 以外の終了コードが返されたため失敗しました"

    テスト スクリプトは Exit 2 コマンドを実行します。スクリプトから 0 以外の終了コードが返された場合、カスタム スクリプト拡張機能は設計上失敗することが予想されます。 (この例では、2 は 0 以外の終了コードです)。この例では、有効にした追加の PowerShell ログにエラーがどのように表示されるかを示します。

  • Change が競合しています: このエラーは、VM にリソース名 Microsoft として既にカスタム スクリプト拡張機能がインストールされていることを示します。Compute.CustomScriptExtension ですが、現在の実行に別のリソース名 CustomScriptExtension を指定しています。

    VM 拡張機能 'CustomScriptExtension' の handlerVersion または autoUpgradeMinorVersion を更新できません。
    変更は、ハンドラー 'Microsoft.Compute.CustomScriptExtension' の他の拡張機能と競合しています。typeHandler バージョン '1.10' と autoUpgradeMinorVersion 'True' です。
    エラーコード: OperationNotAllowed (操作が許可されていません)
    ErrorMessage: VM 拡張機能 'CustomScriptExtension' の handlerVersion または autoUpgradeMinorVersion を更新できません。
    変更は、ハンドラー 'Microsoft.Compute.CustomScriptExtension' の他の拡張機能と競合しています。typeHandler version '1.10' と autoUpgradeMinorVersion 'True' です。
    ErrorTarget:
    StatusCode: 409
    ReasonPhrase: 競合

    リソース名には任意の名前を指定できます。 ただし、カスタム スクリプト拡張機能が既にインストールされている場合は、次のいずれかの操作を実行する必要があります。

    • 後続の実行には同じ名前を使用します。
    • 別のリソース名を使用する前に、最初にその拡張機能リソースを削除します。
  • 無効なファイル URI 構成: このエラーは、カスタム スクリプト拡張機能が、保護された設定で指定されているが、パブリック設定 (またはその逆) で指定されたファイル URI と共に最初にインストールされたことを示します。

    長時間実行操作が状態 '失敗' で失敗しました。
    追加情報: 拡張機能 'CustomScriptExtension' の処理中に VM からエラーが報告されました。
    エラー メッセージ: "無効な構成 - FileUris は、保護された構成セクションとパブリック構成セクションの両方に存在します。1 つのセクションでのみ指定する必要があります。

カスタム スクリプト拡張機能テスト スクリプトの一般的なエラーの解決策

  • "変更が競合しています" エラーを修正するには、 Set-AzVMCustomScriptExtension または Set-AzVMExtensionを再実行しますが、 -Name パラメーターを、VM に既にインストールされているカスタム スクリプト拡張機能リソースのリソース名に設定します。 このサンプル エラーでは、拡張機能を削除するときに、-Name パラメーターとして Microsoft を指定します。Compute.CustomScriptExtension。 ただし、 -Name パラメーターは、VM に既にインストールされている拡張機能リソースのリソース名である必要があります。

    -Nameに使用する名前は、エラーのこの部分のリソース名になります:"変更はハンドラー '<resource-name>' の下の他の拡張機能と競合しています。"

    VM の状態から取得することで、使用する正しいリソース名を確認することもできます。 次のように、 Get-AzVM コマンドレットを入力します。

    $status = Get-AzVM -ResourceGroupName <resource-group> -Name <vm-name> -Status
    $status.Extensions |
    Where-Object Type -EQ 'Microsoft.Compute.CustomScriptExtension' |
    Select-Object Name
    
  • "変更が競合しています" エラーと "FileUris" エラーを軽減するには、 Remove-AzVMCustomScriptExtension コマンドレットを入力して、既存のカスタム スクリプト拡張機能を削除します。

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

    正しくないリソース名を指定した場合、返される StatusCode 値は NoContent

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

    正しいリソース名を指定した場合、返される StatusCode 値は OK

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

関連情報

サードパーティのお問い合わせ窓口に関する免責事項

Microsoftは、このトピックに関する追加情報を見つけるのに役立つサード パーティの連絡先情報を提供します。 この連絡先情報は、予告なしに変更される可能性があります。 Microsoftは、第三者の連絡先情報の正確性を保証するものではありません。