使用Azure Python SDK调用VM Run Command成功但脚本未执行问题排查
我使用Azure Python SDK编写Azure Function,希望通过Run Command功能在VM上执行PowerShell脚本。目前遇到的问题是:所有外部反馈均显示执行成功,包括函数测试输出、VM活动日志,但虚拟机内完全找不到测试用PowerShell命令的执行痕迹。在Azure Portal的VM控制台中手动执行相同命令却能成功生效。
我的代码
import logging import azure.functions as func from azure.mgmt.compute import ComputeManagementClient from azure.identity import ClientSecretCredential def main(req: func.HttpRequest) -> func.HttpResponse: logging.info('Python HTTP trigger function processed a request.') vm_name = req.params.get('vm_name') rg_name = req.params.get('rg_name') if not vm_name: try: req_body = req.get_json() except ValueError: pass else: vm_name = req_body.get('vm_name') if vm_name: client_secret = "xxx" subscription_id = "xxxx" tenant_id = "xxxx" client_id = "xxxx" credentials = ClientSecretCredential(tenant_id, client_id, client_secret) run_command_name = "RunPowerShellScript" run_command = { 'command_id': 'RunPowerShellScript', 'location': 'australiaeast', 'script': 'Write-EventLog -LogName Application -Source "RunCMDTest" -EventID 1 -EntryType Information -Message "Testing Run Command from Azure Function"', } compute_client = ComputeManagementClient(credentials, subscription_id) runcmd = compute_client.virtual_machine_run_commands.begin_create_or_update(rg_name, vm_name, run_command_name, run_command) return func.HttpResponse(f"Executing test on VM {vm_name} in RG {rg_name}.") else: return func.HttpResponse( "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.", status_code=200 )
测试日志
[2023-01-04T11:04:55.293Z] Request URL: 'https://management.azure.com/subscriptions/xxx-subidxxx/resourceGroups/xxxrgxxx/providers/Microsoft.Compute/virtualMachines/xxxvmxxx/runCommands/RunPowerShellScript?api-version=REDACTED'
[2023-01-04T11:04:55.293Z] Request method: 'PUT'
[2023-01-04T11:04:55.293Z] Request headers:
[2023-01-04T11:04:55.293Z] 'Content-Type': 'application/json'
[2023-01-04T11:04:55.293Z] 'Content-Length': '29'
[2023-01-04T11:04:55.293Z] 'Accept': 'application/json, text/json'
[2023-01-04T11:04:55.293Z] 'x-ms-client-request-id': '9e8fcfda-8c1f-11ed-b5f8-00224811eef0'
[2023-01-04T11:04:55.293Z] 'User-Agent': 'azsdk-python-azure-mgmt-compute/29.0.0 Python/3.9.15 (Linux-5.4.0-1094-azure-x86_64-with-glibc2.31)'
[2023-01-04T11:04:55.293Z] 'Authorization': 'REDACTED'
[2023-01-04T11:04:55.293Z] A body is sent with the request
[2023-01-04T11:04:55.723Z] Response status: 200
[2023-01-04T11:04:55.724Z] Response headers:
[2023-01-04T11:04:55.724Z] 'Cache-Control': 'no-cache'
[2023-01-04T11:04:55.725Z] 'Pragma': 'no-cache'
[2023-01-04T11:04:55.726Z] 'Transfer-Encoding': 'chunked'
[2023-01-04T11:04:55.726Z] 'Content-Type': 'application/json; charset=utf-8'
[2023-01-04T11:04:55.726Z] 'Content-Encoding': 'REDACTED'
[2023-01-04T11:04:55.726Z] 'Expires': '-1'
[2023-01-04T11:04:55.726Z] 'Vary': 'REDACTED'
[2023-01-04T11:04:55.727Z] 'Azure-AsyncOperation': 'REDACTED'
[2023-01-04T11:04:55.727Z] 'Azure-AsyncNotification': 'REDACTED'
[2023-01-04T11:04:55.727Z] 'x-ms-ratelimit-remaining-resource': 'Microsoft.Compute/UpdateVM3Min;237,Microsoft.Compute/UpdateVM30Min;1193'
[2023-01-04T11:04:55.727Z] 'Strict-Transport-Security': 'REDACTED'
[2023-01-04T11:04:55.728Z] 'x-ms-request-id': 'c735cde5-a228-418d-a856-856dd0fc1a16'
[2023-01-04T11:04:55.728Z] 'Server': 'Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0'
[2023-01-04T11:04:55.728Z] 'x-ms-ratelimit-remaining-subscription-writes': '1194'
[2023-01-04T11:04:55.729Z] 'x-ms-correlation-request-id': 'REDACTED'
[2023-01-04T11:04:55.729Z] 'x-ms-routing-request-id': 'REDACTED'
[2023-01-04T11:04:55.729Z] 'X-Content-Type-Options': 'REDACTED'
[2023-01-04T11:04:55.729Z] 'Date': 'Wed, 04 Jan 2023 11:04:55 GMT'
[2023-01-04T11:04:55.739Z] Executed 'Functions.func-execute_system_test' (Succeeded, Id=f0f0fa80-c8e1-4d59-a1e1-e40ef75c39e2, Duration=958ms)
问题排查与解决方案
1. 未等待异步操作完成
begin_create_or_update是异步方法,返回的是LROPoller对象,直接返回响应仅表示Azure接受了请求,不代表脚本已在VM上执行。需要添加runcmd.result()等待操作完成:
runcmd = compute_client.virtual_machine_run_commands.begin_create_or_update(rg_name, vm_name, run_command_name, run_command) # 等待异步操作完成 result = runcmd.result() return func.HttpResponse(f"Executed test on VM {vm_name} in RG {rg_name}. Status: {result.status}")
2. 执行上下文与事件源权限问题
Run Command以NT AUTHORITY\SYSTEM账户执行,而手动执行用的是当前登录用户。若事件源RunCMDTest未预先创建,系统账户执行Write-EventLog会静默失败。修改脚本先检查并创建事件源:
if (-not [System.Diagnostics.EventLog]::SourceExists("RunCMDTest")) { [System.Diagnostics.EventLog]::CreateEventSource("RunCMDTest", "Application") } Write-EventLog -LogName Application -Source "RunCMDTest" -EventID 1 -EntryType Information -Message "Testing Run Command from Azure Function"
3. 捕获脚本执行的输出与错误
当前代码未获取Run Command的执行结果,无法确认脚本是否真的成功。添加日志输出执行结果:
result = runcmd.result() logging.info(f"Run Command stdout: {result.output}") logging.info(f"Run Command stderr: {result.error}")
通过日志可查看脚本执行的实际输出,判断是未执行还是执行后无预期效果。
4. 检查Azure Guest Agent状态
Run Command依赖VM上的Azure Guest Agent传递脚本并执行。可在Azure Portal的VM「运行命令」页面查看历史执行记录的详细状态,确认代理是否正常运行。
内容的提问来源于stack exchange,提问作者Matt Auer

