适用于: ✔️ Windows 虚拟机
总结
本文介绍如何在使用自定义脚本扩展或运行命令功能的 PowerShell 脚本中测试和更正失败。
重要
新功能! 请尝试使用 VM 协助解决首要问题。 建议您运行 Windows 的 VM 辅助 或 Linux 的 VM 辅助。 这些基于脚本的诊断工具可帮助你识别影响Azure VM 来宾代理和整体 VM 运行状况的常见问题。
如果在 VM 上遇到性能问题,请先运行这些工具,然后再联系Microsoft 支持部门。
先决条件
概述
假设你使用了 自定义脚本扩展 或 运行命令 功能来运行 PowerShell 脚本。 如果脚本失败,该怎么办? 可以使用多种方法来确定失败原因。
PowerShell 具有多个输出流。 自定义脚本扩展和运行命令脚本的日志将成功流发送到StdOut子状态,将错误流发送到StdErr子状态。 这些子状态属于用于运行自定义脚本扩展或运行命令脚本的扩展。
StdOut和StdErr子状态位于虚拟机(VM)的证书注册点(CRP)实例视图中。 这些子统计信息在多个位置可见,如下表所示。
| 接口 | 如何查看子状态 |
|---|---|
| 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,请运行 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
了解输出
进程创建审核会将事件 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/操作日志的最大大小,请将这些值还原为默认的最大大小:
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 已安装 Custom Script Extension,资源名称为 Microsoft.Compute.CustomScriptExtension,但您当前执行指定的资源名称为 CustomScriptExtension。
无法更新 VM 扩展“CustomScriptExtension”的 handlerVersion 或 autoUpgradeMinorVersion。
更改与处理程序“Microsoft.Compute.CustomScriptExtension”下的其他扩展发生冲突,typeHandler 版本为“1.10”,且 autoUpgradeMinorVersion 为“True”。
ErrorCode:OperationNotAllowed
ErrorMessage:无法更新 VM 扩展“CustomScriptExtension”的 handlerVersion 或 autoUpgradeMinorVersion。
更改与处理程序 'Microsoft.Compute.CustomScriptExtension' 下的其他扩展冲突,具有 typeHandler 版本 '1.10' 和 autoUpgradeMinorVersion 'True'。
ErrorTarget:
StatusCode:409
ReasonPhrase:冲突您可以为资源指定任何您想要的名称。 但是,如果已安装自定义脚本扩展,则必须执行以下操作之一:
- 在后续执行中使用相同的名称。
- 在使用其他资源名称之前,请先删除该扩展资源。
文件 URI 配置无效:此错误指示自定义脚本扩展最初与在受保护设置中指定的文件 URI 一起安装,但现在在公共设置中指定(反之亦然):
长时间运行的操作失败,状态为“失败”。
其他信息:VM 在处理扩展“CustomScriptExtension”时报告了失败。
错误消息:“无效配置 - FileUris 存在于保护和公共配置部分中;它必须仅在一个部分中指定。”
自定义脚本扩展测试脚本中常见错误的解决方案
若要修复“更改存在冲突”错误,请尝试重新运行
Set-AzVMCustomScriptExtension或Set-AzVMExtension将参数设置为-NameVM 上已安装的自定义脚本扩展资源的资源名称。 对于示例错误,删除扩展时,请指定-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 虚拟机扩展失败问题
- 脚本跟踪和日志记录
- Windows操作系统中的已知安全标识符
- Windows日志记录
- 审核成功过程创建事件
- Windows配置 - 设置受害者系统
第三方联系人免责声明
Microsoft提供第三方联系信息,可帮助你查找有关本主题的其他信息。 此联系信息可能会更改,恕不另行通知。 Microsoft不能保证第三方联系信息的准确性。