如何用PowerShell 5.1远程启动Azure VM服务并解决权限问题
问题概述
需要远程启动Azure虚拟机(Azure VM)上的服务,操作必须以管理员身份运行PowerShell才能成功,但当前只能使用PowerShell 5.1版本——该版本的Set-Service命令不支持像7.x那样传入-Credential参数。手中的凭据拥有VM管理员权限,但不知道如何通过命令传递。
现有执行命令
通过以下命令触发远程操作($action取值为stop或start):
$runCommand = Invoke-AzVMRunCommand ` -ResourceGroupName $rg ` -VMName $vm ` -CommandId 'RunPowerShellScript' ` -ScriptPath $scriptPath ` -Parameter @{action = $action}
关联脚本逻辑
对应的服务操作脚本:
$serviceNames = @("service1, service2") foreach($serviceName in $serviceNames){ $service = Get-Service -Name $serviceName if($service){ if($action -ieq "start"){ Set-Service -InputObject $service -Status "Running" } } else{ Write-Output "Service $serviceName not found!" } }
执行场景结果
- 本地笔记本运行:执行挂起
- Azure门户“运行命令”执行:执行挂起
- VM本地直接运行:提示“Service '' cannot be configured due to the following error: Access is denied”
- VM本地以管理员身份启动PowerShell运行:操作成功
解决方案
针对PowerShell 5.1的限制,提供两种可行方法:
方法一:使用CIM命令(推荐)
PowerShell 5.1的CIM系列cmdlet支持-Credential参数,可直接传递管理员凭据操作服务,适配远程执行场景:
param($action) $serviceNames = @("service1", "service2") # 从Azure Key Vault获取凭据(需提前配置密钥保管库及凭据) $secret = Get-AzKeyVaultSecret -VaultName "你的密钥保管库名称" -Name "管理员凭据密钥名" $cred = [System.Management.Automation.PSCredential]::new($secret.Content.UserName, $secret.Content.SecretValue) foreach($serviceName in $serviceNames){ $service = Get-CimInstance -ClassName Win32_Service -Filter "Name='$serviceName'" if($service){ switch($action.ToLower()){ "start" { $service | Invoke-CimMethod -MethodName StartService -Credential $cred } "stop" { $service | Invoke-CimMethod -MethodName StopService -Credential $cred } } } else{ Write-Output "Service $serviceName not found!" } }
说明:禁止明文存储凭据,优先用Azure Key Vault存储并获取,保障安全性。
方法二:启动管理员权限子进程
通过Start-Process启动带管理员权限的PowerShell子进程执行服务操作,适用于本地或需要UAC提权的场景:
param($action) $serviceNames = @("service1", "service2") foreach($serviceName in $serviceNames){ $execScript = @" `$targetService = Get-Service -Name '$serviceName' if(`$targetService){ if('$action' -ieq 'start'){ Set-Service -InputObject `$targetService -Status Running } elseif('$action' -ieq 'stop'){ Set-Service -InputObject `$targetService -Status Stopped } } else { Write-Output 'Service $serviceName not found!' } "@ # 以管理员身份启动子进程执行脚本 Start-Process powershell.exe -ArgumentList "-Command", $execScript -Verb RunAs -Wait }
说明:通过Azure Run Command执行时,若默认Local System权限不足,此方法需结合凭据传递,优先推荐方法一。
内容的提问来源于stack exchange,提问作者igor984
相关产品推荐
相关产品推荐

