news 2026/7/6 10:57:10

Azure CLI安装认证与权限避坑指南:解决az命令不识别、登录失败、权限不足三大断点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Azure CLI安装认证与权限避坑指南:解决az命令不识别、登录失败、权限不足三大断点

1. 这不是又一篇“点几下就装好”的CLI教程——它解决的是你真正卡住的三个节点

Azure CLI 是我每天打开终端第一件事就要确认是否在 PATH 里的工具。不是因为它多酷,而是因为一旦它没装对、没登上去、或者命令总报错,后面所有自动化脚本、资源部署、CI/CD 流水线都会当场停摆——而且错误信息往往只告诉你Authentication failedResource not found,却从不说明到底是 token 过期了、订阅没选对、还是权限根本没配。这篇指南不讲“下载 MSI 包 → 双击 → Finish”这种表面流程,而是聚焦在你实际动手时最常卡住的三个真实断点:安装后az命令不识别、登录后az account show返回空、执行az vm create时提示Insufficient privileges。我会用真实终端日志还原每一步操作现场,解释 Windows PowerShell 和 WSL2 Ubuntu 下路径差异怎么导致命令失效,说明为什么az login --use-device-code在公司网络里大概率失败而az login --tenant却能绕过,拆解az role assignment create命令中--assignee-object-id--assignee-principal-name的本质区别——后者根本不是邮箱地址,而是服务主体的 App ID。如果你刚接触 Azure,这篇能让你跳过前两周反复重装、反复查文档、反复截图问同事的阶段;如果你是 DevOps 工程师,这里会给出你在 Terraform 模块里调用 CLI 前必须校验的 4 个环境变量和 2 个默认配置项。核心关键词已自然嵌入:Azure CLI、安装、认证、使用、az login、az account、权限分配。

2. 安装方案选择逻辑:为什么我坚持不用 MSI,而用 pip 或 apt?

2.1 不是所有安装方式都等价——版本控制与环境隔离才是关键

很多人第一次装 Azure CLI 就直接去官网下载 Windows MSI 安装包,双击一路 Next。这确实快,但埋下了三个后续无法回避的坑:第一,MSI 安装的 CLI 默认绑定到系统 Python(通常是 C:\Python39),而你本地项目可能用 conda 管理 Python 3.11 环境,结果pip list里看不到 azure-cli,az --version显示的是 2.45.0,但python -c "import azure.cli.core; print(azure.cli.core.__version__)"却报错 ModuleNotFoundError;第二,MSI 安装后az命令注册在C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin,这个路径如果没加进系统 PATH,或者被其他工具(比如 VS Code 终端启动时加载的 .bashrc)覆盖,就会出现“命令未找到”;第三,也是最致命的——MSI 安装无法指定版本,你今天装的是 2.52.0,明天微软推个 2.53.0 的 hotfix,它不会自动更新,而你 CI 流水线里写的az group create --name rg-test可能因为新版本改了参数名直接崩掉。

所以我现在所有生产环境一律用pip install azure-cli==2.52.0(带精确版本号)。为什么?因为 pip 安装天然支持虚拟环境隔离。在 WSL2 Ubuntu 里,我执行:

python3 -m venv ~/venv-az source ~/venv-az/bin/activate pip install --upgrade pip pip install azure-cli==2.52.0

这样az命令就严格绑定在这个虚拟环境里,which az返回/home/user/venv-az/bin/az,和系统 Python 完全解耦。更重要的是,pip list | grep azure-cli能一眼看到版本,pip install --force-reinstall azure-cli==2.51.0可以秒级回滚——这在排查某个 CLI 版本和特定 ARM 模板不兼容时,比重装 MSI 快 10 分钟。

提示:Windows 用户别急着关页面。PowerShell 里同样可以用 pip,但必须先确保Get-ExecutionPolicy返回RemoteSignedUnrestricted,否则pip install会被策略拦截。执行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser即可,无需管理员权限。

2.2 Linux/macOS 用户请放弃 curl + bash 一键脚本

Azure 官网提供的curl -L https://aka.ms/InstallAzureCli | bash脚本看似方便,但它会静默下载并执行一个未经校验的 shell 脚本,且默认安装到/opt/az。问题在于:这个路径下的az二进制文件依赖/opt/az/bin/python3,而该 Python 解释器是微软打包进去的精简版,不包含venv模块。这意味着你无法用python3 -m venv创建隔离环境,所有通过pip install安装的扩展(比如az extension add --name aks-preview)都会污染全局。更麻烦的是,当你要升级时,az upgrade命令会尝试替换/opt/az下所有文件,但某些 Linux 发行版(如 CentOS 7)的/opt目录权限为755,非 root 用户无法写入,结果升级失败还留一堆半残文件。

所以我的建议是:Ubuntu/Debian 用户走官方 apt 源,但必须手动添加密钥和源,而不是信curl | bash

# 先卸载可能存在的旧版 sudo apt remove azure-cli # 导入 Microsoft GPG 密钥(注意:这是微软官方密钥,指纹为 BC528686B50D79E339D3721CEB3E94ADBE1229CF) curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /usr/share/keyrings/microsoft.gpg > /dev/null # 添加源(以 Ubuntu 22.04 为例) echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ jammy main" | sudo tee /etc/apt/sources.list.d/azure-cli.list # 更新并安装(注意:这里不加 -y,因为要确认源是否正确加载) sudo apt update sudo apt install azure-cli

这个过程多敲 5 行命令,但换来的是 apt 包管理器的完整生命周期控制:apt list --installed | grep azure-cli查版本,sudo apt install azure-cli=2.52.0-1~jammy锁定版本,sudo apt-mark hold azure-cli防止意外升级。实测下来,在 Jenkins agent 上跑这套流程,CI 任务成功率从 83% 提升到 99.7%,因为再也不会出现“昨天还好的 pipeline,今天突然az login报错No module named 'azure.mgmt.storage'”这种玄学问题。

2.3 macOS 用户的隐藏陷阱:Homebrew 安装后 PATH 不生效

macOS 上用brew install azure-cli是最省事的,但有个 90% 新用户会踩的坑:Homebrew 安装的az/opt/homebrew/bin/az(Apple Silicon)或/usr/local/bin/az(Intel),而你的终端(尤其是 VS Code 内置终端)启动时加载的是~/.zshrc,里面 PATH 可能没包含这两个路径。结果就是:iTerm2 里az --version正常,VS Code 终端里却提示 command not found。

验证方法很简单:在 VS Code 终端里执行echo $PATH,看输出里有没有/opt/homebrew/bin。如果没有,就在~/.zshrc末尾加一行:

export PATH="/opt/homebrew/bin:$PATH"

然后执行source ~/.zshrc。但注意:如果你用的是 Oh My Zsh,且主题启用了plugins=(git),某些主题会重置 PATH,这时得把 export 语句加到~/.zshrc最开头。我自己就因此浪费过 40 分钟——直到我ps -p $$确认终端进程确实是 zsh,又cat /proc/$$/environ | tr '\0' '\n' | grep PATH才发现 PATH 被主题脚本覆盖了。

注意:不要用brew link azure-cli。Homebrew 1.0 之后已废弃 link 命令,强行 link 可能破坏 brew 的依赖追踪,导致brew doctor报一堆 warning。

3. 认证环节深度解析:为什么az login总失败?三个真实场景拆解

3.1 场景一:公司网络下az login卡在浏览器打开,设备代码登录也失败

这是企业用户最高频的问题。你执行az login,终端显示:

To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate.

但打开网页后,输入代码,点击“Next”,页面转圈 30 秒,然后报错:“We couldn't sign you in. Please try again.”。这不是你的网络问题,而是 Azure AD 的条件访问策略(Conditional Access Policy)在作祟。

根本原因在于:设备代码登录(device code flow)需要浏览器向https://login.microsoftonline.com发起跨域请求,而很多企业防火墙会拦截这类 OAuth2 授权码交换的 POST 请求。解决方案不是换网络,而是改用服务主体(Service Principal)登录——它不依赖浏览器,全程走 API 调用:

# 第一步:在 Azure Portal 创建服务主体(需 Global Admin 权限) # 进入 Azure Active Directory → App registrations → New registration # 名称填 my-ci-sp,支持账户类型选 "Accounts in this organizational directory only" # 创建后,记下 Application (client) ID 和 Directory (tenant) ID # 第二步:为服务主体分配 RBAC 角色(关键!) az role assignment create \ --assignee "YOUR-CLIENT-ID" \ --role "Contributor" \ --scope "/subscriptions/YOUR-SUBSCRIPTION-ID" # 第三步:创建客户端密钥(Client Secret) # 在 App registrations → Certificates & secrets → New client secret # 复制生成的 Value(注意:这是唯一一次能看到,关掉页面就再也找不到了) # 第四步:用服务主体登录(这才是真正的无头登录) az login \ --service-principal \ --username "YOUR-CLIENT-ID" \ --password "YOUR-CLIENT-SECRET" \ --tenant "YOUR-TENANT-ID"

这里的关键细节是--scope参数:它必须精确到订阅级别(/subscriptions/xxx),不能是//providers/Microsoft.Authorization,否则权限不生效。我见过太多人漏掉这一步,结果az group list返回空列表,以为登录失败,其实是权限没给到订阅上。

3.2 场景二:个人 Microsoft 账户登录成功,但az account show显示 subscription 为空

你用az login登录了 outlook.com 账户,终端显示You have logged in. Now let us find all the subscriptions to which you have access...,但az account show输出{}。这不是 CLI 故障,而是你的 Microsoft 账户根本没关联任何 Azure 订阅。免费试用订阅(Free Trial)需要主动创建,不是登录就自动开通。

验证方法:打开 Azure Portal ,右上角头像 → Switch directory → 看是否有目录列出。如果没有,说明你还没创建 Azure AD 租户。此时必须:

  1. 访问 https://azure.microsoft.com/free/
  2. 点击 “Start free”,用你的 Microsoft 账户登录
  3. 填写手机号接收验证码(注意:不是邮箱验证码,是短信)
  4. 完成后,Portal 会自动跳转到新创建的订阅页,此时再执行az account list --all --output table,就能看到Name列为Free Trial的条目。

实操心得:az account list默认只显示Enabled状态的订阅。如果你有多个订阅,其中一个是Disabled(比如试用期过了),它不会出现在默认输出里。必须加--all参数才能看到全部。我曾帮同事排查,他以为自己没订阅,其实只是状态是Disabled,执行az account set --subscription "Free Trial"后一切正常。

3.3 场景三:多租户环境下az login登录了错误的 tenant,导致资源找不到

大型企业往往有多个 Azure AD 租户(比如 dev/qa/prod 分离),而az login默认会登录到你上次使用的租户。假设你上周在 dev 租户里工作,今天要操作 prod 环境,执行az group list却返回空,az account show显示的homeTenantId却是 dev 的 ID。

解决方案不是重新登录,而是显式指定 tenant:

# 先查看所有可用 tenant az account list-tenants --output table # 输出类似: # Name TenantId # ---------------------- ------------------------------------ # Contoso Dev xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # Contoso Prod yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy # 强制登录到 prod tenant az login --tenant "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" # 然后切换到目标订阅(注意:tenant 和 subscription 是两个概念) az account set --subscription "Prod Subscription Name"

这里最容易混淆的是--tenant--subscription的关系:--tenant指定身份验证的 Azure AD 目录,--subscription指定资源操作的目标 Azure 订阅。一个 tenant 下可以有多个 subscription,一个 subscription 只能属于一个 tenant。如果你跳过az login --tenant这步,直接az account set,CLI 会尝试在当前 tenant 下查找该 subscription,找不到就报错Subscription not found

4. 使用阶段避坑指南:从az group createaz vm create的 7 个硬核参数真相

4.1az group create--location不是随便填的城市名

新手常犯的错误是把--location当成城市名,比如填--location "East US"--location "us-east-1"(后者是 AWS 的写法)。实际上,Azure 的 location 是预定义的字符串,必须从az account list-locations --query "[].{Name:name, DisplayName:displayName}" --output table获取。常见错误值和正确值对照如下:

错误写法正确写法说明
"East US""eastus"全小写,无空格,连字符
"US East""eastus"Azure 不认“US”前缀
"us-east-1""eastus"这是 AWS 格式,Azure 用eastus,westus2,southeastasia
"China East 2""chinaeast2"中国区 location 全小写无空格

为什么这么严格?因为--location参数最终会作为 ARM 模板中的location属性传给 Resource Manager,而 ARM 服务端只接受预定义枚举值。填错会导致BadRequest错误,提示The provided location 'East US' is not available for resource type 'Microsoft.Resources/resourceGroups'。我建议把常用 location 存成环境变量:

export AZ_LOCATION="eastus" az group create --name my-rg --location $AZ_LOCATION

4.2az vm create--image参数背后是三层镜像体系

--image看似简单,但填错会导致 VM 创建失败或系统异常。Azure 的镜像分三层:

  • Publisher:镜像发布者,如Canonical,MicrosoftWindowsDesktop,RedHat
  • Offer:产品系列,如UbuntuServer,Windows-10,RHEL
  • SKU:具体版本,如18.04-LTS,20h2-evd,8.4

完整格式是Publisher:Offer:SKU:Version,例如:

# Ubuntu 20.04 LTS 最新版本 --image Canonical:UbuntuServer:20.04-LTS:latest # Windows 10 企业版多会话(WVD) --image MicrosoftWindowsDesktop:Windows-10:20h2-evd:latest # RHEL 8.4(注意:不是 8.4-LTS,RHEL 没有 LTS 后缀) --image RedHat:RHEL:8.4:latest

新手常填--image "UbuntuLTS",这是老版本 CLI 的别名,新版已弃用,会报错Image 'UbuntuLTS' not found。正确做法是先查可用镜像:

# 查所有 UbuntuServer 镜像 az vm image list --publisher Canonical --offer UbuntuServer --all --output table # 查特定 SKU 的所有版本 az vm image list --publisher Canonical --offer UbuntuServer --sku 20.04-LTS --all --output table

注意:--all参数必须加,否则只返回最近 5 个版本。生产环境建议用具体版本号(如20.04.202301010)而非latest,避免某天latest指向了不兼容的内核版本。

4.3az vm create--size不是越大越好,内存带宽才是瓶颈

--size参数如Standard_D2s_v3看似直观,但很多人忽略了一个关键事实:Azure VM 的性能瓶颈往往不是 CPU 核数,而是内存带宽。Dsv3系列用的是 Intel Xeon Platinum 8171M(Skylake),其内存带宽为 100 GB/s;而Dav4系列用的是 AMD EPYC 7452,内存带宽达 140 GB/s。如果你跑的是 Redis 或 Elasticsearch 这类内存密集型服务,Dav4的实际吞吐量比同核数的Dsv3高 30%。

验证方法:创建 VM 后,用az vm run-command invoke执行内存带宽测试:

az vm run-command invoke \ --resource-group my-rg \ --name my-vm \ --command-id RunShellScript \ --scripts "sudo apt update && sudo apt install -y sysbench && sysbench memory --memory-block-size=1M --memory-total-size=10G run"

结果中Operations performed数值越高,内存带宽越强。我实测过Standard_D2s_v3平均 12500 ops/sec,Standard_D2as_v4达到 16800 ops/sec。所以选 size 时,先看 workload 类型:CPU 密集型(如编译)选Dsv3,内存密集型(如数据库)选Dav4Eav4

4.4az network vnet create--address-prefixes必须预留足够子网空间

--address-prefixes定义 VNet 的 CIDR 块,比如10.0.0.0/16。新手常填10.0.0.0/24,以为够用。但/24只有 256 个 IP,而一个 VNet 至少要划分子网(subnet)、应用网关、负载均衡器、服务端点等,每个都要占用 IP。更严重的是,Azure 会为每个 VNet 保留前 3 个和最后一个 IP(如10.0.0.0/2410.0.0.0,10.0.0.1,10.0.0.2,10.0.0.255不可用),实际只剩 252 个。

生产环境最低要求是/22(1024 IP),推荐/16(65536 IP)。计算公式:所需 IP 数 = (VM 数 × 1.5) + (服务数 × 10)。比如 10 台 VM + 3 个服务,至少需要(10×1.5)+(3×10)=45个 IP,但必须向上取整到 CIDR 边界,/26(64 IP)勉强够,但无扩展余地,所以直接上/24(256 IP)。

实操心得:VNet 创建后,--address-prefixes无法修改。如果填小了,只能删除重建。我曾因填/24导致后续加 AKS 集群时 subnet 不够,被迫停机 2 小时重建整个网络架构。

4.5az storage account create--kind--access-tier组合决定成本

--kind指存储账户类型:StorageV2(通用 v2)、BlobStorage(仅 Blob)、FileStorage(高级文件)。--access-tier指访问层级:Hot(高频访问)、Cool(低频访问)、Archive(归档)。但很多人不知道,--access-tier只对--kind StorageV2有效,BlobStorage固定为HotFileStorage不支持CoolArchive

成本差异极大:以eastus区域为例,StorageV2+Hot为 $0.018/GB/月,Cool为 $0.01/GB/月,但Cool层级有 30 天最小存储期,提前删除要收 30 天费用。而Archive层级 $0.00099/GB/月,但取回数据要 15 小时,且取回费 $5/10000 次操作。

所以正确组合是:

  • Web 应用静态文件:--kind StorageV2 --access-tier Hot
  • 日志备份(保留 90 天):--kind StorageV2 --access-tier Cool
  • 合规存档(保留 7 年):--kind StorageV2 --access-tier Archive

创建后,用az storage account show --name mystorage --query "primaryEndpoints.blob"验证 endpoint 是否为https://mystorage.blob.core.windows.net/(BlobStorage)或https://mystorage.z13.web.core.windows.net/(Static Website),避免用错 endpoint 导致 404。

4.6az keyvault create--enable-rbac-authorization是权限模型分水岭

Key Vault 有两种权限模型:基于策略(Policy-based)和基于角色(RBAC-based)。--enable-rbac-authorization true启用 RBAC,意味着所有权限(如get secret,list keys)都通过 Azure RBAC 角色分配,而不是 Key Vault 自身的访问策略。

区别在于:

  • Policy-based:在 Key Vault → Access policies 里为每个对象(用户/组/SP)单独授权,最多 1024 条策略,管理复杂。
  • RBAC-based:用标准 Azure 角色(如Key Vault Reader,Key Vault Secrets Officer),可继承、可批量分配,适合大规模环境。

但启用 RBAC 后,az keyvault secret set会报错Forbidden,除非你先分配角色:

# 为服务主体分配 Secrets Officer 角色 az role assignment create \ --role "Key Vault Secrets Officer" \ --assignee-object-id "YOUR-SP-OBJECT-ID" \ --scope "/subscriptions/YOUR-SUB-ID/resourceGroups/YOUR-RG/providers/Microsoft.KeyVault/vaults/YOUR-KV"

注意--scope必须精确到 Key Vault 资源,不能是 resource group 级别。我建议新项目一律启用 RBAC,因为 Policy-based 模型在 Azure Blueprints 和 Bicep 部署中支持度差,且无法与 Entra ID 条件访问策略集成。

4.7az aks create--network-plugin决定网络架构上限

AKS 集群的--network-plugin参数只有两个选项:kubenet(默认)和azure(Azure CNI)。kubenet使用节点子网的 IP,每个节点一个/24子网,Pod IP 从该子网分配;azure直接为每个 Pod 分配 VNet 中的 IP,需要 VNet 有足够地址空间。

性能对比:

  • kubenet:节点最多 250 个 Pod,网络延迟略高(NAT 转发),但 VNet IP 消耗少。
  • azure:节点最多 250 个 Pod(取决于子网大小),网络延迟最低(直连),但一个/24子网只能支持 250 个 Pod,/23支持 500 个。

生产环境必须选azure,因为:

  • Service Mesh(如 Istio)要求 Pod 直连通信
  • Network Policies(如 Calico)在kubenet下不生效
  • Azure Firewall 和 NSG 可以直接对 Pod IP 做规则

创建命令示例:

az aks create \ --resource-group my-rg \ --name my-aks \ --network-plugin azure \ --vnet-subnet-id "/subscriptions/xxx/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/my-vnet/subnets/aks-subnet" \ --docker-bridge-address 172.17.0.1/16 \ --dns-service-ip 10.2.0.10 \ --service-cidr 10.2.0.0/24

其中--vnet-subnet-id必须指向一个独立的 subnet(不能和节点 VM 共用),且该 subnet 的 CIDR 必须大于等于/24。我见过有人用/28(16 IP),结果集群初始化失败,报错Subnet does not have enough IP addresses

5. 常见问题与排查技巧实录:从报错日志反推根因的 12 个速查表

5.1ERROR: The command requires the extension <extension-name>. Please run 'az extension add --name <extension-name>' to install it.

这不是扩展没装,而是扩展版本不兼容。Azure CLI 扩展由社区维护,不同 CLI 版本要求不同扩展版本。比如aks-preview扩展在 CLI 2.52.0 上要求v0.5.50,但在 2.51.0 上要求v0.5.49。当你升级 CLI 后,旧扩展会失效。

排查步骤:

  1. 查看当前扩展版本:az extension list --output table
  2. 查看扩展兼容性:az extension show --name aks-preview --query "metadata.compatibleWithCliCoreVersions"
  3. 如果不匹配,强制重装:az extension remove --name aks-preview && az extension add --name aks-preview --version 0.5.50

实操心得:生产环境 CI 脚本中,永远在az extension add前加az extension remove,避免版本冲突。我曾因跳过这步,导致az aks get-credentials报错AttributeError: 'NoneType' object has no attribute 'get',查了 3 小时才发现是aks-preview扩展版本错位。

5.2ERROR: Operation returned an invalid status 'Bad Request'(无更多日志)

这是 Azure REST API 返回的通用错误,根源在请求体(request body)格式错误。CLI 命令最终会序列化为 JSON 发给 ARM,而 JSON 字段名大小写、空值处理、数组结构都必须严格符合 Swagger 定义。

典型场景:

  • az vm create --tags "env=prod app=web"--tags要求键值对,不能是字符串。正确写法:--tags env=prod app=web
  • az storage account create --https-only false--https-only是布尔参数,不加值即为 true,加false会报错。正确写法:删掉该参数,或用--http-only
  • az network vnet subnet create --address-prefixes "10.0.1.0/24"--address-prefixes是数组,必须用空格分隔多个值,单个值不加引号。正确写法:--address-prefixes 10.0.1.0/24

调试方法:加--debug参数,看 CLI 发出的原始 HTTP 请求:

az vm create --name test-vm --resource-group my-rg --image UbuntuLTS --debug 2>&1 | grep "Request URL\|Request body"

从日志里复制Request body的 JSON,用 JSONLint 验证格式,再对照 ARM Template Reference 检查字段名是否正确。

5.3ERROR: No module named 'azure.mgmt.*'

这是 CLI 扩展依赖缺失。Azure CLI 核心只包含基础命令(az group,az account),所有云服务命令(az vm,az storage)都是通过扩展实现的。azure.mgmt.*是 Azure SDK for Python 的管理库,每个扩展依赖特定版本。

根因有两个:

  • 扩展安装不完整:pip install azure-cli时网络中断,部分依赖没装全
  • Python 环境混乱:系统 Python 和虚拟环境混用,pip list显示有azure-mgmt-compute,但az vm list仍报错

解决方案:

  1. 清理所有扩展:az extension list --query "[].name" -o tsv | xargs -I {} az extension remove --name {}
  2. 重装核心依赖:pip install --force-reinstall azure-mgmt-compute azure-mgmt-storage azure-mgmt-network
  3. 重装扩展:az extension add --name azure-firewall(举例)

注意:不要用pip install azure-cli[vm],CLI 官方不支持这种安装方式,会破坏依赖树。

5.4ERROR: Authentication failed. Please check your credentials.az login后仍报错)

这不是凭证错,而是 CLI 缓存了过期的 token。Azure CLI 的 token 默认有效期 1 小时,但有时因系统时间偏差、token 刷新失败,缓存的 token 会变成无效状态。

验证方法:cat ~/.azure/accessTokens.json | jq '.[] | select(.expiresOn < now | strftime("%Y-%m-%d %H:%M"))'(Linux/macOS),如果输出非空,说明有 token 过期。

强制刷新:

# 清除所有 token 缓存 az account clear # 重新登录(加 --use-device-code 避免浏览器问题) az login --use-device-code # 验证 az account show

如果仍失败,检查系统时间:date,误差超过 5 分钟会导致 OAuth2 签名验证失败。用sudo ntpdate -s time.nist.gov同步时间。

5.5ERROR: ResourceGroupNotFoundaz group show报错)

az group show --name my-rg报错,但 Portal 里明明存在。这是因为 CLI 默认查询当前订阅,而该资源组在另一个订阅里。

解决方案:

  1. 查看所有订阅:az account list --all --output table
  2. 找到资源组所在订阅的nameid
  3. 切换订阅:az account set --subscription "Subscription Name"
  4. 再执行az group show

更高效的方法是直接指定订阅 ID 查询:

az group show --name my-rg --subscription "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

5.6ERROR: InvalidTemplate(ARM 模板部署失败)

az deployment group create报错InvalidTemplate,通常是因为模板 JSON 格式错误或参数不匹配。

快速定位:

  • 模板语法:az bicep build --file main.bicep(如果是 Bicep)或jq empty template.json(JSON 格式校验)
  • 参数文件:az deployment group validate --template-file template.json --parameters parameters.json,它会返回具体哪一行参数错

常见错误:

  • parameters.json"location": "[resourceGroup().location]"[ ]是 ARM 表达式,不能在参数文件里用,必须在模板里用
  • 模板里"[parameters('location')]"写成"[parameters('Location')]":参数名大小写敏感
  • int()函数传入字符串"123"正常,但传入"123abc"会报错

5.7ERROR: The client '<object-id>' with object id '<object-id>' does not have authorization to perform action 'Microsoft.Authorization/roleAssignments/write' over scope '/subscriptions/...' or the scope is invalid.

这是权限不足,但错误信息误导人。<object-id>是你的用户或服务主体 ID,Microsoft.Authorization/roleAssignments/write是分配 RBAC 角色的权限,但问题往往不在这个动作本身,而在--scope参数。

根因:

  • --scope指向了不存在的资源(如拼错 resource group 名)
  • --scope指向了你没有Microsoft.Authorization/roleAssignments/read权限的上级 scope(如 subscription 级别,但你只有 resource group 级别权限)

验证--scope是否有效:

# 检查 resource group 是否存在 az group show --name my-rg # 检查你对该 scope 的权限
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 10:56:53

深度解析高危钓鱼链:从攻击原理到企业纵深防御实战

1. 项目概述&#xff1a;当“鱼钩”伪装成“钥匙”最近在安全圈里&#xff0c;和几个老朋友聊起企业防护的现状&#xff0c;大家都有一个共同的感受&#xff1a;传统的边界防火墙、入侵检测系统&#xff08;IDS&#xff09;越来越像一道“马奇诺防线”&#xff0c;看似固若金汤…

作者头像 李华
网站建设 2026/7/6 10:56:32

MATLAB多旅行商路径规划工具:同起点同终点的遗传算法求解方案

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;一套即装即用的MATLAB路径优化工具&#xff0c;专为多个旅行商从同一城市出发、最终全部返回该城市的场景设计。核心采用遗传算法实现TSP变体求解&#xff0c;包含完整可运行主程序main.m&#xff0c;无需额外工…

作者头像 李华
网站建设 2026/7/6 10:50:57

IS31FL3731与MK64FN1M0VDC12驱动LED矩阵实战指南

1. 硬件选型与核心特性解析 在LED矩阵驱动领域&#xff0c;IS31FL3731和MK64FN1M0VDC12的组合堪称黄金搭档。IS31FL3731是Lumissil公司推出的专业级LED驱动芯片&#xff0c;而MK64FN1M0VDC12则是NXP基于ARM Cortex-M4内核的高性能微控制器。这套组合特别适合需要复杂动画效果和…

作者头像 李华
网站建设 2026/7/6 10:50:29

ISO 15739 Visual Noise 实战:3步量化人眼感知噪声,对比SNR差异

ISO 15739 Visual Noise实战&#xff1a;3步量化人眼感知噪声与SNR差异解析当我们在昏暗环境下拍摄照片时&#xff0c;经常会发现画面上布满令人不悦的颗粒感——这就是典型的图像噪声表现。传统SNR&#xff08;信噪比&#xff09;指标虽然能反映噪声强度&#xff0c;却无法准确…

作者头像 李华
网站建设 2026/7/6 10:50:17

MongoDB博客数据建模实战:嵌入、引用与混合策略

1. 为什么博客应用的数据建模不能照搬关系型数据库那一套&#xff1f;刚接手一个技术博客平台重构项目时&#xff0c;我第一反应是画ER图、分用户表、文章表、标签表、评论表——结果两周后在MongoDB里跑出一堆$lookup聚合慢得像卡顿的旧手机。后来翻遍官方文档和十几个真实上线…

作者头像 李华
网站建设 2026/7/6 10:48:14

如何5分钟提取视频字幕:Video-subtitle-extractor本地OCR工具完全指南

如何5分钟提取视频字幕&#xff1a;Video-subtitle-extractor本地OCR工具完全指南 【免费下载链接】video-subtitle-extractor 视频硬字幕提取&#xff0c;生成srt文件。无需申请第三方API&#xff0c;本地实现文本识别。基于深度学习的视频字幕提取框架&#xff0c;包含字幕区…

作者头像 李华