Home / Azure

AzureHow-toBeginner

Azure VM at 100% CPU: finding the process without logging in

Use Run Command and VM insights to find the process behind high CPU on Windows and Linux VMs, even when RDP or SSH is too slow to use.

Deepak Bhardwaj2 min read

Applies toAzure VMs with the VM agent, Windows Server and Linux

When a VM is pinned at 100% CPU, RDP and SSH often time out. Run Command goes through the VM agent instead, so it still works.

Windows: top processes

az vm run-command invoke -g rg-prod -n vm-app-01 --command-id RunPowerShellScript --scripts '
$cores = (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors
Get-Counter "\Process(*)\% Processor Time" -SampleInterval 2 -MaxSamples 2 |
  Select-Object -ExpandProperty CounterSamples |
  Where-Object { $_.InstanceName -notin "_total","idle" } |
  Sort-Object CookedValue -Descending | Select-Object -First 10 InstanceName,
    @{n="CPU%";e={[math]::Round($_.CookedValue / $cores, 1)}}
' --query "value[0].message" -o tsv

To find which service a svchost or w3wp is running:

Get-CimInstance Win32_Process -Filter "Name='w3wp.exe'" | Select-Object ProcessId, CommandLine   # shows the app pool
tasklist /svc /fi "imagename eq svchost.exe"

Linux: top processes

az vm run-command invoke -g rg-prod -n vm-app-02 --command-id RunShellScript \
  --scripts "top -b -n 1 -o %CPU | head -20; echo; uptime" --query "value[0].message" -o tsv

For per-thread detail, or for processes in containers: ps -eLo pid,tid,pcpu,comm --sort=-pcpu | head.

Usual suspects

Process Common cause
MsMpEng.exe / AV agent Scanning a busy data or log folder. Add exclusions as approved by security.
TiWorker.exe, TrustedInstaller Windows Update servicing. Usually temporary.
w3wp.exe, java, dotnet An application hot path, or a runaway loop. Take a dump or profile.
sqlservr.exe Expensive queries. Use Query Store or DMVs.
kworker, high %wa Not really CPU: the system is waiting on disk IO

Check the history

Was this a spike or a trend? With VM insights:

InsightsMetrics
| where TimeGenerated > ago(7d) and Computer == "vm-app-01"
| where Namespace == "Processor" and Name == "UtilizationPercentage"
| summarize avg(Val), max(Val) by bin(TimeGenerated, 1h)
| render timechart

Fix options

  • Kill or restart the offending process or service, after capturing evidence (a dump with procdump -ma <pid> on Windows, gcore or jstack on Linux).
  • Resize the VM if the load is legitimate:
    az vm resize -g rg-prod -n vm-app-01 --size Standard_D8s_v5   # restarts the VM
    
  • On B-series VMs, check CPU Credits Remaining. When credits run out, the VM is capped at its baseline and looks "pinned".

Tip

Add a CPU alert with dynamic thresholds so it learns the normal daily pattern and only fires on unusual load.