Azure CLI Cheatsheet
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)
# 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 tsvKey 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.
# List only function-app names and their states
az functionapp list \
--query "[].{name:name, state:state}" \
--output tableSetup & Authentication
Install
macOS
brew update && brew install azure-cli
# Upgrade later
brew upgrade azure-cliLinux — Debian/Ubuntu
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bashLinux — RHEL/Fedora/openSUSE
# 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-cliWindows
# winget (recommended)
winget install Microsoft.AzureCLI
# Or download the MSI from https://aka.ms/installazurecliwindowsVerify installation
az --version
# azure-cli 2.x.x
# ...Sign In
Interactive browser login (most common)
az login
# Opens a browser tab; authenticate and return to the terminal.Device-code flow (headless servers, SSH sessions)
az login --use-device-code
# Prints a code + URL; open the URL on any device, enter the code.Service principal with password (CI/CD)
az login \
--service-principal \
--username "$ARM_CLIENT_ID" \
--password "$ARM_CLIENT_SECRET" \
--tenant "$ARM_TENANT_ID"Service principal with certificate
az login \
--service-principal \
--username "$ARM_CLIENT_ID" \
--certificate /path/to/cert.pem \
--tenant "$ARM_TENANT_ID"Managed identity (inside Azure VMs / App Services)
az login --identity
# Uses the VM's system-assigned managed identity — no credentials required.Sign out
az logoutManage Subscriptions
# 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.
# 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.groupTip: Create a project-scoped config. The
az configfile at~/.azure/configis global; team-specific defaults can be placed in./azconfigwithin a project and loaded withAZURE_CONFIG_DIR=./azconfig az <command>.
Output Formats
| Format | Flag | Use case |
|---|---|---|
| JSON | --output json | Default; pipe into jq |
| Table | --output table | Human-readable terminal view |
| TSV | --output tsv | Shell scripts; no headers |
| YAML | --output yaml | Readable config dumps |
| None | --output none | Suppress output in CI |
# Set table as the default output format
az config set core.output=table
# Override for a single command
az functionapp list --output jsonJMESPath Queries (--query)
The --query flag filters or reshapes the JSON response before it is printed.
# 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 tsvGlobal Flags
| Flag | Description |
|---|---|
--output / -o | Output format: json, table, tsv, yaml, none |
--query | JMESPath expression to filter output |
--resource-group / -g | Resource group (omit if a default is set) |
--subscription | Override the active subscription for one command |
--debug | Verbose HTTP-level debug output |
--verbose | More detailed status messages |
--only-show-errors | Suppress warnings, print only errors |
--no-wait | Start an async operation and return immediately |
Create a Service Principal for CI/CD
# 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 IDSecurity note: Scope the service principal as narrowly as possible. Prefer
--role Readerfor read-only pipelines and use federated OIDC credentials instead of passwords when supported by your CI platform.
Function Apps
List Function Apps
# 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 tableInspect a Function App
# 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 ProcessOrdersFollow Live Application Logs
This is the most-used day-to-day command when debugging a running Function App.
# Stream application logs in real time (Ctrl-C to stop)
az webapp log tail \
--name my-function-app \
--resource-group my-rgWhy
az webapp log? Azure Function Apps run on the App Service / Web Apps platform under the hood. Theaz webapp logcommands work seamlessly for Function Apps. The neweraz functionapp log tailalias also works in recent CLI versions: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:
# 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 verboseDownload logs as a ZIP archive
az webapp log download \
--name my-function-app \
--resource-group my-rg \
--log-file ./function-logs.zipStart, Stop, and Restart
# 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-rgApplication Settings (Environment Variables)
Function App application settings are injected as environment variables at runtime.
# 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 tsvTip: Changing application settings triggers an automatic restart of the Function App.
Deployment
Deploy a ZIP package
# 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 zipDeploy from a local source (run-from-package)
# 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 trueView deployment history
az functionapp deployment list \
--name my-function-app \
--resource-group my-rg \
--output tableScaling & Plan
# 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 tsvNote: Consumption and Flex Consumption plans scale automatically; you do not manage instance counts directly.
Function Apps — Quick Reference
| Task | Command |
|---|---|
| List all Function Apps | az functionapp list --output table |
| Show one app | az functionapp show -n <app> -g <rg> |
| Tail live logs | az webapp log tail -n <app> -g <rg> |
| List triggers | az functionapp function list -n <app> -g <rg> |
| Set app setting | az functionapp config appsettings set -n <app> -g <rg> --settings K=V |
| List app settings | az functionapp config appsettings list -n <app> -g <rg> |
| Deploy ZIP | az functionapp deploy -n <app> -g <rg> --src-path pkg.zip --type zip |
| Restart | az functionapp restart -n <app> -g <rg> |
| Stop | az functionapp stop -n <app> -g <rg> |
| Start | az 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)
# 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-containerAccount name + key
export AZURE_STORAGE_ACCOUNT="mystorageaccount"
export AZURE_STORAGE_KEY="base64key=="
az storage blob list --container-name my-containerAzure AD (recommended for production)
# 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 loginTip: Set
AZURE_STORAGE_ACCOUNTand eitherAZURE_STORAGE_KEYorAZURE_STORAGE_CONNECTION_STRINGin your shell profile to avoid repeating them on every command.
Manage Storage Accounts
# 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 tsvManage Containers
# 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 mystorageaccountList Blobs
# 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 tableCount Blobs Under a Prefix
Use the JMESPath length() function to count the results without any extra tools.
# 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 tsvCount blobs matching a pattern in a script
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 listautomatically pages through all results, so the count is always the full total — not just the first page.
Upload Blobs
# 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-unchangedDownload Blobs
# 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
# 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
# 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.
# 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
| Task | Command |
|---|---|
| List containers | az storage container list --account-name <acct> --output table |
| Create container | az storage container create --name <c> --account-name <acct> |
| List blobs | az storage blob list --container-name <c> --account-name <acct> --output table |
| List blobs by prefix | az storage blob list ... --prefix <prefix> |
| Count blobs by prefix | az storage blob list ... --prefix <p> --query "length(@)" --output tsv |
| Upload file | az storage blob upload --container-name <c> --file <f> --name <n> --account-name <acct> |
| Upload directory | az storage blob upload-batch --source <dir> --destination <c> --account-name <acct> |
| Download blob | az storage blob download --container-name <c> --name <n> --file <f> --account-name <acct> |
| Download batch | az storage blob download-batch --source <c> --destination <dir> --account-name <acct> |
| Delete blob | az storage blob delete --container-name <c> --name <n> --account-name <acct> |
| Delete by pattern | az storage blob delete-batch --source <c> --pattern "prefix/*" --account-name <acct> |
| Generate blob SAS | az storage blob generate-sas --container-name <c> --name <n> --permissions r --expiry <date> --account-name <acct> |