适用于:✔️ Windows VM
本文介绍如何在使用自定义脚本扩展或运行命令功能的 PowerShell 脚本中测试和更正失败。
先决条件
概述
假设你使用了 自定义脚本扩展 或 运行命令 功能来运行 PowerShell 脚本。 如果脚本失败,该怎么办? 可以使用多种方法来确定失败原因。
PowerShell 具有多个输出流。 自定义脚本扩展和运行命令脚本的日志将成功流发送到StdOut
子状态,并将错误流发送到StdErr
子状态。 这些子统计信息属于用于运行自定义脚本扩展脚本或运行命令脚本的扩展。
StdErr
子StdOut
统计信息位于虚拟机(VM)的证书注册点(CRP)实例视图中。 这些子统计信息在多个位置可见,如下表所示。
Interface | 如何查看子状态 |
---|---|
Azure 门户 |
|
Azure PowerShell | 输入 Get-AzVM cmdlet 以获取 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,请结合set-log
以下选项运行wevtutil
:
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
了解输出
进程创建审核会将事件 ID 4688 和事件 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”事件包括 cmdlet 名称和输出。
如果运行 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 以仅检索最近一小时。 值 604800000 将检索最近一周。
$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 >= '$startTimeUtc'
and
@SystemTime <= '$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 >= '$startTimeUtc'
and
@SystemTime <= '$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 脚本日志记录所做的更改,请执行以下步骤:
如果以前增加了安全日志或 Microsoft-Windows-PowerShell/Operational 日志的最大大小,请将这些值还原为默认的最大大小:
wevtutil set-log "Security" /ms:20971520 wevtutil set-log "Microsoft-Windows-PowerShell/Operational" /ms:15728640
关闭进程创建审核:
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v "ProcessCreationIncludeCmdLine_Enabled" /t REG_DWORD /d 0 /f
关闭听录:
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"
关闭模块日志记录:
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 "*"
关闭脚本块日志记录:
reg add "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v "EnableScriptBlockLogging" /t REG_DWORD /d 0 /f
删除听录文件夹:
Remove-Item -Path 'C:\Transcripts' -Force -Recurse
备份并清除安全日志和 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/操作日志,而无需备份它们:
wevtutil clear-log Security wevtutil clear-log Microsoft-Windows-PowerShell/Operational
VM 上的测试运行命令日志记录
将 Test-CustomScriptExtension.ps1 测试脚本下载到当前本地目录。 然后,使用 Invoke-AzVMRunCommand cmdlet 在 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 cmdlet 在 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 cmdlet 在 VM 上运行该测试脚本。 必须指定与其他ExtensionType
CustomScriptExtension
几个参数更改一起的参数。 使用 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
自定义脚本扩展测试脚本中的常见错误
非零退出代码:运行 Test-CustomScriptExtension.ps1 脚本后,预期会收到以下错误消息:
长时间运行的操作失败,状态为“失败”。
其他信息:VM 在处理扩展“CustomScriptExtension”时报告了失败。
错误消息:“命令执行已完成,但失败,因为它返回了非零退出代码:'2'”测试脚本运行
Exit 2
命令,如果脚本返回非零退出代码,则自定义脚本扩展应设计失败。 (在此示例中,2 是非零退出代码。此示例演示如何在启用的额外 PowerShell 日志记录中显示失败。更改存在冲突:此错误指示 VM 已将自定义脚本扩展安装为资源名称Microsoft.Compute.CustomScriptExtension,但你正在为当前执行指定 CustomScriptExtension 的其他资源名称:
无法更新 VM 扩展“CustomScriptExtension”的 handlerVersion 或 autoUpgradeMinorVersion。
更改与处理程序“Microsoft.Compute.CustomScriptExtension”下的其他扩展冲突,类型Handler 版本为“1.10”和 autoUpgradeMinorVersion“True”。
ErrorCode:OperationNotAllowed
ErrorMessage:无法更新 VM 扩展“CustomScriptExtension”的 handlerVersion 或 autoUpgradeMinorVersion。
更改与处理程序“Microsoft.Compute.CustomScriptExtension”下的其他扩展冲突,类型Handler 版本为“1.10”和 autoUpgradeMinorVersion“True”。
ErrorTarget:
StatusCode:409
ReasonPhrase: Conflict可以指定资源名称所需的任何名称。 但是,如果已安装自定义脚本扩展,则必须执行以下操作之一:
- 对后续执行使用相同的名称。
- 在使用其他资源名称之前,请先删除该扩展资源。
文件 URI 配置无效:此错误指示自定义脚本扩展最初与在受保护设置中指定的文件 URI 一起安装,但现在在公共设置中指定(反之亦然):
长时间运行的操作失败,状态为“失败”。
其他信息:VM 在处理扩展“CustomScriptExtension”时报告了失败。
错误消息:“配置无效 - FileUris 存在于受保护和公共配置部分中;它必须在一个节中指定。”
自定义脚本扩展测试脚本中常见错误的解决方案
若要修复“更改存在冲突”错误,请尝试重新运行
Set-AzVMCustomScriptExtension
或Set-AzVMExtension
将参数设置为-Name
VM 上已安装的自定义脚本扩展资源的资源名称。 对于示例错误,删除扩展时,请指定-Name
Microsoft.Compute.CustomScriptExtension 的参数。 但是,参数-Name
必须是 VM 上已安装的扩展资源的任意资源名称。要用于
-Name
的名称将是错误此部分中的资源名称:“更改与处理程序”resource-name>“<下的其他扩展冲突。还可以通过从 VM 状态获取资源名称来验证要使用的正确资源名称。 输入 Get-AzVM cmdlet,如下所示:
$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 cmdlet 来删除现有的自定义脚本扩展:
$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
参考
- Azure Windows VM 扩展故障排除
- 脚本跟踪和日志记录
- Windows 操作系统中的已知安全标识符
- Windows 日志记录
- 审核成功过程创建事件
- Windows 配置 - 设置受害者系统
联系我们寻求帮助
如果你有任何疑问或需要帮助,请创建支持请求或联系 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区。
第三方联系人免责声明
Microsoft 会提供第三方联系信息来帮助你查找有关本主题的其他信息。 此联系信息可能会更改,恕不另行通知。 Microsoft 不保证第三方联系信息的准确性。