Azure CLI Cheatsheet

·Updated April 13th, 2026

Azure CLI Cheatsheet

The Azure CLI (az) is Microsoft’s cross-platform command-line tool for managing Azure resources. It is written in Python, ships as a single binary, and speaks JSON by default — making it scriptable, pipeline-friendly, and easy to combine with tools like jq.

Quick-Start (60 seconds)

bash
# 1. Install (macOS / Homebrew)
brew install azure-cli

# 2. Sign in
az login

# 3. Pick a subscription
az account list --output table
az account set --subscription "My Subscription"

# 4. Tail a Function App's live logs
az webapp log tail \
  --name my-function-app \
  --resource-group my-rg

# 5. Count blobs under a prefix in a storage container
az storage blob list \
  --account-name mystorageaccount \
  --container-name my-container \
  --prefix "2026/03/" \
  --query "length(@)" \
  --output tsv

Key Concepts

Resource Groups — Azure resources live inside a resource group (--resource-group / -g). Setting a default with az config set defaults.group=my-rg removes the need to pass -g on every command.

Subscriptions — An account can have many subscriptions. Use az account set to switch the active one. Every resource lives under exactly one subscription.

Output formats — The CLI defaults to json. Common alternatives:

  • --output table — human-readable tabular view
  • --output tsv — tab-separated; ideal for shell scripts
  • --output yaml — YAML; readable alternative to JSON
  • --output none — suppress output (useful in CI)

JMESPath queries — The --query flag accepts JMESPath expressions to filter and reshape JSON output before it is printed, without needing jq.

bash
# List only function-app names and their states
az functionapp list \
  --query "[].{name:name, state:state}" \
  --output table

Setup & Authentication

Install

macOS

bash
brew update && brew install azure-cli

# Upgrade later
brew upgrade azure-cli

Linux — Debian/Ubuntu

bash
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Linux — RHEL/Fedora/openSUSE

bash
# openSUSE Tumbleweed / Leap
sudo zypper install azure-cli

# RHEL / CentOS / Fedora (via Microsoft repo)
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
sudo dnf install azure-cli

Windows

powershell
# winget (recommended)
winget install Microsoft.AzureCLI

# Or download the MSI from https://aka.ms/installazurecliwindows

Verify installation

bash
az --version
# azure-cli                         2.x.x
# ...

Sign In

Interactive browser login (most common)

bash
az login
# Opens a browser tab; authenticate and return to the terminal.

Device-code flow (headless servers, SSH sessions)

bash
az login --use-device-code
# Prints a code + URL; open the URL on any device, enter the code.

Service principal with password (CI/CD)

bash
az login \
  --service-principal \
  --username "$ARM_CLIENT_ID" \
  --password "$ARM_CLIENT_SECRET" \
  --tenant  "$ARM_TENANT_ID"

Service principal with certificate

bash
az login \
  --service-principal \
  --username "$ARM_CLIENT_ID" \
  --certificate /path/to/cert.pem \
  --tenant "$ARM_TENANT_ID"

Managed identity (inside Azure VMs / App Services)

bash
az login --identity
# Uses the VM's system-assigned managed identity — no credentials required.

Sign out

bash
az logout

Manage Subscriptions

bash
# List all subscriptions your account can access
az account list --output table

# Show the currently active subscription
az account show

# Switch to a specific subscription (by name or ID)
az account set --subscription "My Dev Subscription"
az account set --subscription "00000000-0000-0000-0000-000000000000"

Configure Defaults

Storing frequently-used values avoids repeating --resource-group and --location on every command.

bash
# Set a default resource group and Azure region
az config set defaults.group=my-rg
az config set defaults.location=eastus

# View current defaults
az config get defaults

# Clear a default
az config unset defaults.group

Tip: Create a project-scoped config. The az config file at ~/.azure/config is global; team-specific defaults can be placed in ./azconfig within a project and loaded with AZURE_CONFIG_DIR=./azconfig az <command>.


Output Formats

FormatFlagUse case
JSON--output jsonDefault; pipe into jq
Table--output tableHuman-readable terminal view
TSV--output tsvShell scripts; no headers
YAML--output yamlReadable config dumps
None--output noneSuppress output in CI
bash
# Set table as the default output format
az config set core.output=table

# Override for a single command
az functionapp list --output json

JMESPath Queries (--query)

The --query flag filters or reshapes the JSON response before it is printed.

bash
# Extract a single field
az account show --query "name" --output tsv

# Project multiple fields into a table
az functionapp list \
  --query "[].{Name:name, State:state, SKU:sku}" \
  --output table

# Filter by value
az functionapp list \
  --query "[?state=='Running'].name" \
  --output tsv

# Count items
az storage blob list \
  --container-name my-container \
  --account-name mystorageaccount \
  --query "length(@)" \
  --output tsv

Global Flags

FlagDescription
--output / -oOutput format: json, table, tsv, yaml, none
--queryJMESPath expression to filter output
--resource-group / -gResource group (omit if a default is set)
--subscriptionOverride the active subscription for one command
--debugVerbose HTTP-level debug output
--verboseMore detailed status messages
--only-show-errorsSuppress warnings, print only errors
--no-waitStart an async operation and return immediately

Create a Service Principal for CI/CD

bash
# Create a SP with Contributor role scoped to a resource group
az ad sp create-for-rbac \
  --name "my-app-ci" \
  --role Contributor \
  --scopes "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/my-rg" \
  --output json

# Output includes appId, password, tenant — store these as CI secrets:
# ARM_CLIENT_ID     = appId
# ARM_CLIENT_SECRET = password
# ARM_TENANT_ID     = tenant
# ARM_SUBSCRIPTION_ID = your subscription ID

Security note: Scope the service principal as narrowly as possible. Prefer --role Reader for read-only pipelines and use federated OIDC credentials instead of passwords when supported by your CI platform.


Function Apps

List Function Apps

bash
# List every Function App in the active subscription
az functionapp list --output table

# List Function Apps in a specific resource group
az functionapp list \
  --resource-group my-rg \
  --output table

# Show only names of running apps
az functionapp list \
  --query "[?state=='Running'].name" \
  --output tsv

# Show name, state, location, and runtime
az functionapp list \
  --query "[].{Name:name, State:state, Location:location, Runtime:kind}" \
  --output table

Inspect a Function App

bash
# Show full details for one app
az functionapp show \
  --name my-function-app \
  --resource-group my-rg

# Get just the default hostname (the public URL)
az functionapp show \
  --name my-function-app \
  --resource-group my-rg \
  --query "defaultHostName" \
  --output tsv

# List individual functions (triggers) within an app
az functionapp function list \
  --name my-function-app \
  --resource-group my-rg \
  --output table

# Show details of a specific function trigger
az functionapp function show \
  --name my-function-app \
  --resource-group my-rg \
  --function-name ProcessOrders

Follow Live Application Logs

This is the most-used day-to-day command when debugging a running Function App.

bash
# Stream application logs in real time (Ctrl-C to stop)
az webapp log tail \
  --name my-function-app \
  --resource-group my-rg

Why az webapp log? Azure Function Apps run on the App Service / Web Apps platform under the hood. The az webapp log commands work seamlessly for Function Apps. The newer az functionapp log tail alias also works in recent CLI versions:

bash
az functionapp log tail \
  --name my-function-app \
  --resource-group my-rg

Enable application logging first

Log streaming requires application logging to be turned on. Check and enable it:

bash
# Check current logging configuration
az webapp log show \
  --name my-function-app \
  --resource-group my-rg

# Enable application-level logging to the filesystem
az webapp log config \
  --name my-function-app \
  --resource-group my-rg \
  --application-logging filesystem \
  --level information

# Enable with verbose detail (useful during debugging)
az webapp log config \
  --name my-function-app \
  --resource-group my-rg \
  --application-logging filesystem \
  --level verbose

Download logs as a ZIP archive

bash
az webapp log download \
  --name my-function-app \
  --resource-group my-rg \
  --log-file ./function-logs.zip

Start, Stop, and Restart

bash
# Stop a Function App (billing for Dedicated plans continues)
az functionapp stop \
  --name my-function-app \
  --resource-group my-rg

# Start a stopped Function App
az functionapp start \
  --name my-function-app \
  --resource-group my-rg

# Restart (stop + start in one command)
az functionapp restart \
  --name my-function-app \
  --resource-group my-rg

Application Settings (Environment Variables)

Function App application settings are injected as environment variables at runtime.

bash
# List all current application settings (values visible in plain text)
az functionapp config appsettings list \
  --name my-function-app \
  --resource-group my-rg \
  --output table

# Set one or more settings
az functionapp config appsettings set \
  --name my-function-app \
  --resource-group my-rg \
  --settings \
    DATABASE_URL="postgresql://user:pass@host/db" \
    FEATURE_FLAG_X="true"

# Delete a setting
az functionapp config appsettings delete \
  --name my-function-app \
  --resource-group my-rg \
  --setting-names DATABASE_URL

# Read the value of a single setting
az functionapp config appsettings list \
  --name my-function-app \
  --resource-group my-rg \
  --query "[?name=='DATABASE_URL'].value" \
  --output tsv

Tip: Changing application settings triggers an automatic restart of the Function App.


Deployment

Deploy a ZIP package

bash
# Zip-push deployment (most portable)
az functionapp deployment source config-zip \
  --name my-function-app \
  --resource-group my-rg \
  --src ./dist/function-package.zip

# Newer `az functionapp deploy` command (equivalent, recommended for CLI 2.40+)
az functionapp deploy \
  --name my-function-app \
  --resource-group my-rg \
  --src-path ./dist/function-package.zip \
  --type zip

Deploy from a local source (run-from-package)

bash
# Upload the package to a storage account and configure run-from-package
az functionapp deploy \
  --name my-function-app \
  --resource-group my-rg \
  --src-path ./dist/function-package.zip \
  --type zip \
  --async true

View deployment history

bash
az functionapp deployment list \
  --name my-function-app \
  --resource-group my-rg \
  --output table

Scaling & Plan

bash
# Show the App Service plan used by the Function App
az functionapp show \
  --name my-function-app \
  --resource-group my-rg \
  --query "appServicePlanId" \
  --output tsv

# Scale out a Dedicated (non-Consumption) plan — increase worker count
az appservice plan update \
  --name my-app-service-plan \
  --resource-group my-rg \
  --number-of-workers 3

# Get the current scale-out worker count
az appservice plan show \
  --name my-app-service-plan \
  --resource-group my-rg \
  --query "sku.capacity" \
  --output tsv

Note: Consumption and Flex Consumption plans scale automatically; you do not manage instance counts directly.


Function Apps — Quick Reference

TaskCommand
List all Function Appsaz functionapp list --output table
Show one appaz functionapp show -n <app> -g <rg>
Tail live logsaz webapp log tail -n <app> -g <rg>
List triggersaz functionapp function list -n <app> -g <rg>
Set app settingaz functionapp config appsettings set -n <app> -g <rg> --settings K=V
List app settingsaz functionapp config appsettings list -n <app> -g <rg>
Deploy ZIPaz functionapp deploy -n <app> -g <rg> --src-path pkg.zip --type zip
Restartaz functionapp restart -n <app> -g <rg>
Stopaz functionapp stop -n <app> -g <rg>
Startaz functionapp start -n <app> -g <rg>

Blob Storage

Authentication Options

Most az storage commands require credentials. Choose one approach and apply it consistently across commands.

Connection string (quickest for one-off tasks)

bash
# Pass inline
az storage blob list \
  --connection-string "DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net" \
  --container-name my-container

# Or export to an environment variable (cleaner)
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=...;AccountKey=..."
az storage blob list --container-name my-container

Account name + key

bash
export AZURE_STORAGE_ACCOUNT="mystorageaccount"
export AZURE_STORAGE_KEY="base64key=="

az storage blob list --container-name my-container
bash
# First ensure your identity has the "Storage Blob Data Reader" (or Contributor) role
az storage blob list \
  --account-name mystorageaccount \
  --container-name my-container \
  --auth-mode login

Tip: Set AZURE_STORAGE_ACCOUNT and either AZURE_STORAGE_KEY or AZURE_STORAGE_CONNECTION_STRING in your shell profile to avoid repeating them on every command.


Manage Storage Accounts

bash
# List all storage accounts in the active subscription
az storage account list --output table

# List storage accounts in a specific resource group
az storage account list \
  --resource-group my-rg \
  --output table

# Show details of one account (including endpoints)
az storage account show \
  --name mystorageaccount \
  --resource-group my-rg

# Get the primary account key
az storage account keys list \
  --account-name mystorageaccount \
  --resource-group my-rg \
  --query "[0].value" \
  --output tsv

Manage Containers

bash
# List all containers in a storage account
az storage container list \
  --account-name mystorageaccount \
  --output table

# Show metadata and properties for one container
az storage container show \
  --name my-container \
  --account-name mystorageaccount

# Create a container (private by default)
az storage container create \
  --name my-container \
  --account-name mystorageaccount

# Create a container with public blob-level read access
az storage container create \
  --name public-assets \
  --account-name mystorageaccount \
  --public-access blob

# Delete a container (and all its contents — irreversible)
az storage container delete \
  --name my-container \
  --account-name mystorageaccount

List Blobs

bash
# List all blobs in a container (flat listing)
az storage blob list \
  --container-name my-container \
  --account-name mystorageaccount \
  --output table

# List blobs under a specific prefix (simulates a "folder")
az storage blob list \
  --container-name my-container \
  --account-name mystorageaccount \
  --prefix "logs/2026/03/" \
  --output table

# Show only blob names (not metadata)
az storage blob list \
  --container-name my-container \
  --account-name mystorageaccount \
  --prefix "logs/2026/" \
  --query "[].name" \
  --output tsv

# List blobs and include their sizes in a readable table
az storage blob list \
  --container-name my-container \
  --account-name mystorageaccount \
  --query "[].{Name:name, Size:properties.contentLength, Modified:properties.lastModified}" \
  --output table

Count Blobs Under a Prefix

Use the JMESPath length() function to count the results without any extra tools.

bash
# Count all blobs in a container
az storage blob list \
  --container-name my-container \
  --account-name mystorageaccount \
  --query "length(@)" \
  --output tsv

# Count blobs under a specific prefix
az storage blob list \
  --container-name my-container \
  --account-name mystorageaccount \
  --prefix "uploads/2026/03/" \
  --query "length(@)" \
  --output tsv

Count blobs matching a pattern in a script

bash
PREFIX="uploads/2026/03/"
COUNT=$(az storage blob list \
  --container-name my-container \
  --account-name mystorageaccount \
  --prefix "$PREFIX" \
  --query "length(@)" \
  --output tsv)

echo "Found $COUNT blobs under prefix '$PREFIX'"

Note on pagination: az storage blob list automatically pages through all results, so the count is always the full total — not just the first page.


Upload Blobs

bash
# Upload a single file
az storage blob upload \
  --container-name my-container \
  --account-name mystorageaccount \
  --file ./data/report.csv \
  --name reports/2026/report.csv

# Upload and overwrite if it already exists
az storage blob upload \
  --container-name my-container \
  --account-name mystorageaccount \
  --file ./data/report.csv \
  --name reports/2026/report.csv \
  --overwrite

# Upload an entire local directory (batch)
az storage blob upload-batch \
  --source ./dist/assets \
  --destination my-container \
  --account-name mystorageaccount \
  --destination-path "assets/v2/"

# Upload only changed files (based on MD5 checksum)
az storage blob upload-batch \
  --source ./dist/assets \
  --destination my-container \
  --account-name mystorageaccount \
  --destination-path "assets/v2/" \
  --skip-unchanged

Download Blobs

bash
# Download a single blob
az storage blob download \
  --container-name my-container \
  --account-name mystorageaccount \
  --name reports/2026/report.csv \
  --file ./local-report.csv

# Download all blobs from a container to a local directory
az storage blob download-batch \
  --source my-container \
  --destination ./local-backup \
  --account-name mystorageaccount

# Download blobs matching a prefix pattern
az storage blob download-batch \
  --source my-container \
  --destination ./local-backup \
  --account-name mystorageaccount \
  --pattern "logs/2026/03/*"

Delete Blobs

bash
# Delete a single blob
az storage blob delete \
  --container-name my-container \
  --account-name mystorageaccount \
  --name reports/2026/old-report.csv

# Delete all blobs matching a pattern (dry-run: add --dry-run to preview)
az storage blob delete-batch \
  --source my-container \
  --account-name mystorageaccount \
  --pattern "tmp/*"

# Delete all blobs under a prefix
az storage blob delete-batch \
  --source my-container \
  --account-name mystorageaccount \
  --pattern "logs/2024/*"

Copy Blobs

bash
# Copy a blob within the same account
az storage blob copy start \
  --source-container source-container \
  --source-blob path/to/source.csv \
  --destination-container dest-container \
  --destination-blob path/to/dest.csv \
  --account-name mystorageaccount

# Copy all blobs matching a pattern across containers
az storage blob copy start-batch \
  --source-container source-container \
  --destination-container dest-container \
  --account-name mystorageaccount \
  --pattern "exports/2026/*"

Generate SAS Tokens

SAS (Shared Access Signature) tokens grant time-limited, scoped access without sharing your account key.

bash
# Generate a read-only SAS token for a single blob (expires 2026-12-31)
az storage blob generate-sas \
  --container-name my-container \
  --name reports/2026/report.csv \
  --account-name mystorageaccount \
  --permissions r \
  --expiry "2026-12-31T23:59:59Z" \
  --output tsv

# Generate a container-level SAS with read + list permissions
az storage container generate-sas \
  --name my-container \
  --account-name mystorageaccount \
  --permissions rl \
  --expiry "2026-12-31T23:59:59Z" \
  --output tsv

# Build a full blob URL with the SAS token embedded
BLOB="reports/2026/report.csv"
TOKEN=$(az storage blob generate-sas \
  --container-name my-container \
  --name "$BLOB" \
  --account-name mystorageaccount \
  --permissions r \
  --expiry "2026-12-31T23:59:59Z" \
  --output tsv)

echo "https://mystorageaccount.blob.core.windows.net/my-container/${BLOB}?${TOKEN}"

Blob Storage — Quick Reference

TaskCommand
List containersaz storage container list --account-name <acct> --output table
Create containeraz storage container create --name <c> --account-name <acct>
List blobsaz storage blob list --container-name <c> --account-name <acct> --output table
List blobs by prefixaz storage blob list ... --prefix <prefix>
Count blobs by prefixaz storage blob list ... --prefix <p> --query "length(@)" --output tsv
Upload fileaz storage blob upload --container-name <c> --file <f> --name <n> --account-name <acct>
Upload directoryaz storage blob upload-batch --source <dir> --destination <c> --account-name <acct>
Download blobaz storage blob download --container-name <c> --name <n> --file <f> --account-name <acct>
Download batchaz storage blob download-batch --source <c> --destination <dir> --account-name <acct>
Delete blobaz storage blob delete --container-name <c> --name <n> --account-name <acct>
Delete by patternaz storage blob delete-batch --source <c> --pattern "prefix/*" --account-name <acct>
Generate blob SASaz storage blob generate-sas --container-name <c> --name <n> --permissions r --expiry <date> --account-name <acct>