有效使用 Azure CLI

为清楚起见,将内联使用 Bash 脚本。 附录中列出了 Windows 批处理或 PowerShell 示例,可用于生成类似的示例。

输出格式(json、table 或 tsv)

  1. json 格式是 CLI 的默认格式,旨在提供最全面的信息。 如果要使用其他格式,请使用 --output 参数替代单个命令调用,或使用 az configure 更新全局默认值。 请注意,JSON 格式保留双引号,因而一般不适合用于脚本编写。

  2. table 适用于获取重点信息的摘要,特别是对于列表命令。 如果不喜欢默认表格式的字段(或者没有默认格式),可以使用 --output json 查看所有信息,或者利用 --query 指定喜欢的格式。

    az vm show -g my_rg -n my_vm --query "{name: name, os:storageProfile.imageReference.offer}" -otable
    Name    Os
    ------  ------------
    my_vm   UbuntuServer
    
  3. tsv 适用于简洁的输出和编写脚本。 tsv 将去除 JSON 格式保留的双引号。 要为 TSV 指定所需的格式,请使用 --query 参数。

    export vm_ids=$(az vm list -d -g my_rg --query "[?powerState=='VM running'].id" -o tsv)
    az vm stop --ids $vm_ids
    

将值从一个命令传递到另一个命令

  1. 如果将多次使用某个值,请将该值分配给变量。 请注意以下示例中 -o tsv 的用法:

    running_vm_ids=$(az vm list -d -g my_rg --query "[?powerState=='VM running'].id" -o tsv)
    
  2. 如果某个值只使用一次,请考虑使用管道:

    az vm list --query "[?powerState=='VM running'].name" | grep my_vm
    
  3. 对于列表,请考虑以下建议:

    如需加强对结果的控制,请使用“for”循环:

    #!/usr/bin/env bash
    for vm in $(az vm list -d -g my_rg --query "[?powerState=='VM running'].id" -o tsv); do
        echo stopping $vm
        az vm stop --ids $vm
        if [ $? -ne 0 ]; then
            echo "Failed to stop $vm"
            exit 1
        fi
        echo $vm stopped
    done
    

    或者,使用 xargs,并考虑使用 -P 标志来并行运行操作以提高性能:

    az vm list -d -g my_rg --query "[?powerState=='VM stopped'].id" -o tsv | xargs -I {} -P 10 az vm start --ids "{}"
    

    最后,Azure CLI 具有内置支持,可并行处理具有多个 --ids 的命令,以实现 xargs 的相同效果。 请注意,@- 用于从管道获取值:

    az vm list -d -g my_rg --query "[?powerState=='VM stopped'].id" -o tsv | az vm start --ids @-
    

异步操作

许多命令和组都会在其长时间运行的操作以及专用 wait 命令中公开 --no-wait 标志。 它们非常适用于特定方案:

  1. 在不依赖清理来执行某些后续操作(例如删除资源组)的情况下清理资源:

    az group delete -n my_rg --no-wait
    
  2. 需要并行创建多个独立资源。 这类似于创建并联接线程:

    az vm create -g my_rg -n vm1 --image centos --no-wait
    az vm create -g my_rg -n vm2 --image centos --no-wait
    
    subscription=$(az account show --query "id" -otsv)
    vm1_id="/subscriptions/$subscription/resourceGroups/my_rg/providers/Microsoft.Compute/virtualMachines/vm1"
    vm2_id="/subscriptions/$subscription/resourceGroups/my_rg/providers/Microsoft.Compute/virtualMachines/vm2"
    az vm wait --created --ids $vm1_id $vm2_id
    

泛型更新参数

CLI 中的大多数更新命令都具有三个泛型参数:--add--set--remove。 这些参数功能强大,但通常不如更新命令中通常使用的强类型参数方便。 CLI 为最常见的方案提供了强类型参数,以便于使用,但如果未列出你要设置的属性,泛型更新参数通常会提供一个路径来解除阻止,而无需等待新发布。

  1. 泛型更新语法并不是最便于使用的,因此请多一些耐心。
  2. 验证更新命令是否公开了 Generic Update Arguments 组。 如果没有,将需要提出问题,但如果公开了,则可以使用它们来尝试你的方案。
  3. 在相关资源上使用 show 命令,确定应在泛型参数中提供的路径。 例如,在尝试 az vm update 之前,请运行 az vm show 确定正确的路径。 通常,你将使用点语法来访问字典属性,并使用括号为列表编制索引。
  4. 请查看工作示例以开始使用。 az vm update -h 就提供了几个不错的示例。
  5. --set--add 采用 <key1>=<value1> <key2>=<value2> 格式的键值对列表。 使用它们可构造有意义的有效负载。 如果语法消息过多,请考虑使用 JSON 字符串。 例如,将新的数据磁盘附加到 VM:
    az vm update -g my_rg -n my_vm --add storageProfile.dataDisks "{\"createOption\": \"Attach\", \"managedDisk\": {\"id\": \"/subscriptions/0b1f6471-1bf0-4dda-aec3-cb9272f09590/resourceGroups/yg/providers/Microsoft.Compute/disks/yg-disk\"}, \"lun\": 1}"
    
  6. 你可能会发现,利用 CLI 的 @{file} 约定将 JSON 放入文件并进行加载会更有用。 这将上面的命令简化为:
    az vm update -g my_rg -n my_vm --add storageProfile.dataDisks @~/my_disk.json
    

通用资源命令 - az resource

在某些情况下,你感兴趣的服务可能没有 CLI 命令覆盖。 可以通过 az resource create/show/list/delete/update/invoke-action 命令来使用这些资源。 以下是一些建议:

  1. 如果仅涉及 create/update,请考虑使用 az group deployment create。 利用 Azure 快速入门模板来获取工作示例。
  2. 有关请求有效负载、URL 和 API 版本,请查看 REST API 引用。 例如,查看社区对如何创建 AppInsights 的评论。

REST API 命令 - az rest

如果泛型更新参数和 az resource 都不能满足你的需要,则可以使用 az rest 命令调用 REST API。 它使用登录凭据自动进行身份验证,并设置标头 Content-Type: application/json

这对于调用 Microsoft Graph API 非常有用,CLI 命令当前不支持此 API (#12946)。

例如,为了更新应用程序redirectUris,我们使用以下命令调用更新应用程序 REST API:

# Line breaks for legibility only

# Get the application
az rest --method GET
        --uri 'https://graph.microsoft.com/v1.0/applications/b4e4d2ab-e2cb-45d5-a31a-98eb3f364001'

# Update `redirectUris` for `web` property
az rest --method PATCH
        --uri 'https://graph.microsoft.com/v1.0/applications/b4e4d2ab-e2cb-45d5-a31a-98eb3f364001'
        --body '{"web":{"redirectUris":["https://myapp.com"]}}'

--uri-parameters 用于 OData 格式的请求时,请确保在不同的环境中对 $ 进行转义:在 Bash 中,将 $ 转义为 \$,在 PowerShell 中,将 $ 转义为 `$

引号问题

这之所以成为一个问题,是因为当命令行界面(Bash、Zsh、Windows 命令提示符和 PowerShell 等)分析 CLI 命令时,它将解释引号和空格。 如果不确定 shell 的用法,请始终参阅文档:

为了避免出现意外结果,此处提供了一些建议:

  1. 如果值包含空格,则必须将其括在引号中。

  2. 在 Bash 或 Windows PowerShell 中,将解释单引号和双引号,而在 Windows 命令提示符中,仅处理双引号,这意味着单引号将被解释为值的一部分。

  3. 如果命令仅在 Bash(或 Zsh)上运行,则使用单引号可以保留其中的内容。 提供内联 JSON 时,这可能非常有用。 例如,以下命令可在 bash 中正常工作:'{"foo": "bar"}'

  4. 如果命令在 Windows 命令提示符上运行,则必须使用双引号。 如果值包含双引号,则必须对其进行转义:"i like to use \" a lot"。 与上面的命令等效的命令提示符为:"{\"foo\": \"bar\"}"

  5. 将计算 bash 中包含在双引号内的导出变量。 如果未得到想要的结果,请再次使用 \ 对其进行转义(如 "\$var"),或者使用单引号 '$var'

  6. 一些 CLI 参数(包括泛型更新参数)采用空格分隔的值列表,如 <key1>=<value1> <key2>=<value2>。 由于键名和值可以采用任意字符串,其中可能包含空格,因此必须使用引号。 包装对,而不是单个键或值。 因此 "my name"=john 是错误的。 请改用 "my name=john"。 例如:

    az webapp config appsettings set -g my_rg -n my_web --settings "client id=id1" "my name=john"
    
  7. 使用 CLI 的 @<file> 约定从文件加载,从而绕过 shell 的解释机制:

    az ad app create --display-name my-native --native-app --required-resource-accesses @manifest.json
    
  8. 当 CLI 参数表示它接受以空格分隔的列表时,以下是接受的格式:

    • --arg foo bar:没问题。 未加引号的空格分隔列表
    • --arg "foo" "bar":正常:加引号的空格分隔列表
    • --arg "foo bar":错误。 这是一个包含空格的字符串,而不是以空格分隔的列表。
  9. 在 PowerShell 中运行 Azure CLI 命令时,当参数包含 PowerShell 的特殊字符(例如 @)时,将发生分析错误。 要解决此问题,可以通过在特殊字符之前添加 ` 对其进行转义,或者可以在参数两边加单引号或双引号 '/"。 例如,az group deployment create --parameters @parameters.json 在 PowerShell 中不起作用,因为 @ 被分析为展开符号。 要解决此问题,可以将参数更改为 `@parameters.json'@parameters.json'

  10. --query 与命令一起使用时,需要在 shell 中对 JMESPath 的某些字符进行转义。 例如,在 Bash 中执行以下代码:

    # Wrong, as the dash needs to be quoted in a JMESPath query
    $ az version --query azure-cli
    az version: error: argument --query: invalid jmespath_type value: 'azure-cli'
    
    # Wrong, as the dash needs to be quoted in a JMESPath query, but quotes are interpreted by Bash
    $ az version --query "azure-cli"
    az version: error: argument --query: invalid jmespath_type value: 'azure-cli'
    
    # Correct
    $ az version --query '"azure-cli"'
    "2.5.1"
    
    $ az version --query \"azure-cli\"
    "2.5.1"
    
    $ az version --query "\"azure-cli\""
    "2.5.1"
    

    在命令提示符中:

    > az version --query "\"azure-cli\""
    "2.5.1"
    
    > az version --query \"azure-cli\"
    "2.5.1"
    

    在 PowerShell 中(需要额外转义):

    > az version --query '\"azure-cli\"'
    "2.5.1"
    
    > az version --query "\`"azure-cli\`""
    "2.5.1"
    
    > az version --query "\""azure-cli\"""
    "2.5.1"
    
    > az --% version --query "\"azure-cli\""
    "2.5.1"
    
    > az --% version --query \"azure-cli\"
    "2.5.1"
    
  11. 解决引号问题的最佳方法是运行带有 --debug 标志的命令。 它显示了 CLI 在 Python 语法中接收到的实际参数。 例如,在 Bash 中执行以下代码:

    # Wrong, as quotes and spaces are interpreted by Bash
    $ az {"key": "value"} --debug
    Command arguments: ['{key:', 'value}', '--debug']
    
    # Wrong, as quotes are interpreted by Bash
    $ az {"key":"value"} --debug
    Command arguments: ['{key:value}', '--debug']
    
    # Correct
    $ az '{"key":"value"}' --debug
    Command arguments: ['{"key":"value"}', '--debug']
    
    # Correct
    $ az "{\"key\":\"value\"}" --debug
    Command arguments: ['{"key":"value"}', '--debug']
    

在代理后面工作

代理在公司网络背后很常见,或者由 Fiddler、mitmproxy 等跟踪工具引入。如果代理使用自签名证书,则 CLI 使用的 Python 请求库将引发 SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",)。 可以通过两种方法来处理此错误:

  1. 将环境变量 REQUESTS_CA_BUNDLE 设置为 PEM 格式的 CA 捆绑证书文件的路径。 如果你经常在公司代理后面使用 CLI,则建议这样做。 在 Windows 上,CLI 使用的默认 CA 捆绑位于 C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\Lib\site-packages\certifi\cacert.pem,在 Linux 上,该捆绑位于 /opt/az/lib/python3.6/site-packages/certifi/cacert.pem。 可以将代理服务器的证书追加到此文件,或将内容复制到另一个证书文件,然后将 REQUESTS_CA_BUNDLE 设置为该文件。 例如:

    <Original cacert.pem>
    
    -----BEGIN CERTIFICATE-----
    <Your proxy's certificate here>
    -----END CERTIFICATE-----
    

    一个常见的问题为是否应该设置 HTTP_PROXYHTTPS_PROXY 环境变量,答案是视情况而定。 对于 Windows 上的 Fiddler,默认情况下,它在启动时充当系统代理,你无需进行任何设置。 如果该选项处于关闭状态或使用其他无法用作系统代理的工具,则应设置它们。 由于来自 CLI 的几乎所有流量都基于 SSL,因此仅应设置 HTTPS_PROXY。 如果你不确定,那就设置它们,但请记住在代理关闭后取消设置。 对于 fiddler,默认值为 http://localhost:8888

    某些代理要求进行身份验证,因此 HTTP_PROXYHTTPS_PROXY 环境变量的格式应包含身份验证,例如 HTTPS_PROXY="https://username:password@proxy-server:port"。 底层 python 库需要此信息。 有关详细信息,请参阅如何为 Azure 库配置代理

    有关其他详细信息,请查看 Stefan 的博客

  2. 通过设置环境变量 AZURE_CLI_DISABLE_CONNECTION_VERIFICATION=1,禁用跨 Azure CLI 的证书检查。 这并不安全,但在短期内效果很好,例如捕获特定命令的网络跟踪并在完成后立即将其关闭。 由于潜在的 SDK 限制,这可能不适用于某些数据平面命令。

并发生成

如果在生成计算机上使用 az,并且可以并行运行多个作业,则存在登录令牌在两个生成作业之间共享的风险,因为这些作业以同一 OS 用户身份运行。 为避免此类混淆,请将 AZURE_CONFIG_DIR 设置为应存储登录令牌的目录。 它可以是随机创建的文件夹,也可以只是 jenkins 工作区的名称,例如 AZURE_CONFIG_DIR=.

附录

Windows 批处理脚本,用于保存到变量并在以后使用

ECHO OFF
SETLOCAL
FOR /F "tokens=* USEBACKQ" %%F IN (`az vm list -d -g my_rg --query "[?powerState=='VM running'].id" -o tsv`) DO (
    SET "vm_ids=%%F %vm_ids%"  :: construct the id list
)
az vm stop --ids %vm_ids% :: CLI stops all VMs in parallel

Windows PowerShell 脚本,用于保存到变量并在以后使用

$vm_ids=(az vm list -d -g my_rg --query "[?powerState=='VM running'].id" -o tsv)
az vm stop --ids $vm_ids # CLI stops all VMs in parallel

Windows 批处理脚本,用于循环访问列表

ECHO OFF
SETLOCAL
FOR /F "tokens=* USEBACKQ" %%F IN (`az vm list -d -g my_rg --query "[?powerState=='VM running'].id" -o tsv`) DO (
    ECHO Stopping %%F
    az vm stop --ids %%F
)

Windows PowerShell 脚本,用于循环访问列表

$vm_ids=(az vm list -d -g my_rg --query "[?powerState=='VM running'].id" -o tsv)
foreach ($vm_id in $vm_ids) {
    Write-Output "Stopping $vm_id"
    az vm stop --ids $vm_id
}

CLI 环境变量

环境变量 描述
AZURE_CONFIG_DIR 用于配置文件、日志和遥测的全局配置目录。 如果未指定,则默认为 ~/.azure
AZURE_EXTENSION_DIR 扩展的安装目录。 如果未指定,则默认为全局配置目录中的 cliextensions 目录。