C#调用Azure Run Command API在Linux VM执行Shell脚本相关问题咨询
问题解决方案
1. 仅返回202状态码无执行结果的解决
原因
Azure 虚拟机Run Command接口为异步设计,返回202状态码仅代表命令提交成功,而非执行完成,不会在首次响应中直接返回执行结果。
解决步骤
- 首次请求返回202后,从响应头的
Azure-AsyncOperation字段获取执行状态查询地址 - 按固定间隔(推荐2-3秒)轮询该查询地址,直到返回结果中的
status字段变为Succeeded或Failed - 执行成功后,从返回结果的
properties.output.value字段读取命令执行的标准输出、标准错误内容
2. 给shell脚本传递参数的实现
实现方式
RunShellScript命令支持parameters参数,你可以将需要传入myscript.sh的参数按顺序添加到该字段中,脚本内直接通过$1、$2等位置变量读取参数即可。
请求Body构造要求
- 保留
commandId为RunShellScript script字段填写你虚拟机上myscript.sh的绝对路径,例如/home/user/myscript.sh- 新增
parameters列表,每个参数为包含name和value的对象,参数会按你添加的顺序传入脚本
修改后的完整C#代码示例
using (var client = new HttpClient()) { // 构造请求Body,包含脚本路径和传入参数 Body body = new Body { commandId = "RunShellScript", // 替换为你虚拟机上myscript.sh的实际绝对路径 script = new List<string> { "/home/youruser/myscript.sh" }, // 传入参数,按顺序对应脚本的$1、$2... parameters = new List<Parameter> { new Parameter { name = "arg1", value = "第一个参数值" }, new Parameter { name = "arg2", value = "第二个参数值" } } }; // 生成Bearer Token var azureServiceTokenProvider = new AzureServiceTokenProvider(); string managementApiUrl = "https://management.azure.com/"; var accessToken = await azureServiceTokenProvider.GetAccessTokenAsync(managementApiUrl, "你的租户ID"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); // 调用POST提交命令 HttpResponseMessage response = await client.PostAsJsonAsync("https://management.azure.com/subscriptions/你的订阅ID/resourceGroups/你的资源组名/providers/Microsoft.Compute/virtualMachines/simpleLinuxVM/runCommand?api-version=2021-03-01", body); if (response.StatusCode == HttpStatusCode.Accepted) { // 获取异步查询地址 string asyncOperationUrl = response.Headers.GetValues("Azure-AsyncOperation").FirstOrDefault(); string operationResult = null; // 轮询查询执行状态 while (true) { HttpResponseMessage statusResponse = await client.GetAsync(asyncOperationUrl); if (statusResponse.IsSuccessStatusCode) { operationResult = await statusResponse.Content.ReadAsStringAsync(); // 解析状态,可使用JsonNode或者自定义类解析返回内容 var statusJson = JsonNode.Parse(operationResult); string status = statusJson["status"].GetValue<string>(); if (status == "Succeeded" || status == "Failed") { break; } } // 等待2秒再轮询 await Task.Delay(2000); } // 输出最终执行结果 Console.WriteLine($"执行结果:{operationResult}"); } else { Console.WriteLine($"请求失败,状态码:{response.StatusCode}"); string responseContent = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseContent); } } // 用到的自定义类定义参考 public class Body { public string commandId { get; set; } public List<string> script { get; set; } public List<Parameter> parameters { get; set; } } public class Parameter { public string name { get; set; } public string value { get; set; } }
内容的提问来源于stack exchange,提问作者MSE Black
相关产品推荐
相关产品推荐

