你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

如何在 Bash 脚本语言中使用 Azure CLI

Azure CLI 参考命令可以以多种 脚本语言执行。 如果你不熟悉 Bash 和 Azure CLI,本文是开始学习之旅的绝佳位置。 请像完成教程一样,逐步阅读本文,轻松学习如何在 Bash 脚本语言中使用 Azure CLI。

在这篇文章中,你将学会如何:

  • 将查询结果格式化为 JSON 字典或数组
  • 将输出格式设置为 JSON、表或 TSV
  • 查询、筛选和设置单个值和多个值的格式
  • 使用 if/exists/then 和 case 语法
  • 使用for循环
  • 使用 grep、sed、paste 和 bc 命令
  • 填充和使用 shell 和环境变量

如果没有 Azure 订阅,请在开始之前创建一个 Azure 免费帐户

启动 Bash

使用 Azure Cloud ShellAzure CLI 的本地安装启动 Bash。 本文假设使用 Azure Cloud Shell 运行 Bash,或者在 Docker 容器中本地运行 Azure CLI。

查询字典结果

始终只返回单个对象的命令返回 JSON 字典。 字典是使用键访问的无序对象。 在本文中,我们将首先使用“帐户显示”命令查询 Account 对象。

az account show
az account show --output json # JSON is the default format

以下 JSON 字典输出包含一些为简洁起见而省略的字段,并删除了标识信息。

bash-5.1# az account show
{
  "environmentName": "AzureCloud",
  "isDefault": true,
  "managedByTenants": [],
  "name": "My test subscription",
  "state": "Enabled",
  "user": {
    "name": "user@contoso.com",
    "type": "user"
  }
}

将输出的格式设置为 YAML

使用 --output yaml 参数(或 -o yaml)以 yaml 格式设置输出格式(纯文本数据序列化格式)。 YAML 往往比 JSON 更容易阅读,并且很容易映射到该格式。 某些应用程序和 CLI 命令采用 YAML 作为配置输入,而不是 JSON。

az account show --output yaml

有关将输出格式化为 yaml 的详细信息,请参阅 YAML 输出格式

将输出的格式设置为表格

使用 --output table 参数 (或 -o table) 将输出格式化为 ASCII 表。 嵌套对象不包括在表输出中,但仍可以作为查询的一部分进行筛选。

az account show --output table

有关将输出格式化为表的详细信息,请参阅 表输出格式

查询和设置单个值和嵌套值的格式

以下查询演示如何查询单个值,包括 JSON 字典输出中的嵌套值。 此集中的最后一个查询演示如何使用 -o tsv 参数设置输出的格式。 该参数将结果作为以制表符和换行符分隔的值返回。 此操作对于去除返回值中的引号非常有用,因为这样可以将输出用于其他需要以某种形式处理文本的命令和工具(如本文稍后所示)。

az account show --query name # Querying a single value
az account show --query name -o tsv # Removes quotation marks from the output

az account show --query user.name # Querying a nested value
az account show --query user.name -o tsv # Removes quotation marks from the output

从数组查询和格式化属性

以下查询演示如何获取 JSON 数组中的属性。 获取订阅属性,显示为订阅表。

az account list --query "[].{subscription_id:id, name:name, isDefault:isDefault}" -o table

此查询返回的结果类似于:

Subscription_id                       Name                                               IsDefault
------------------------------------  -------------------------------------------------  -----------
11111111-3ddc-45ce-8334-c7b28a9e1c3a  C & L Azure developer experience content projects  False
22222222-8f1c-409b-af1e-8e2e65d9b90a  DevCenter - Infrastructure - Dogfood               False
33333333-c080-42a7-8973-1aa853ab4df3  Babel                                              False

查询和格式化多个值,包括嵌套值

若要获取多个属性,请将表达式放在方括号 [ ] (多选列表)中作为逗号分隔的列表。 以下查询演示如何使用多个输出格式查询 JSON 字典输出中的多个值。

az account show --query [name,id,user.name] # return multiple values
az account show --query [name,id,user.name] -o table # return multiple values as a table

有关返回多个值的详细信息,请参阅 “获取多个值”。

重命名查询中的属性

以下查询演示如何在查询多个值时使用 { } (多选哈希) 运算符来获取字典而不是数组。 它还演示了在查询结果中重命名属性。

az account show --query "{SubscriptionName: name, SubscriptionId: id, UserName: user.name}" # Rename the values returned
az account show --query "{SubscriptionName: name, SubscriptionId: id, UserName: user.name}" -o table # Rename the values returned in a table

有关重命名查询中的属性的详细信息,请参阅 查询中的重命名属性

查询布尔值

布尔值假定为 true,因此 "[?isDefault]" 命令的 az account list 查询语法返回当前默认订阅。 若要获取 false 值,必须使用转义字符,例如 \

以下查询演示了查询订阅中的所有帐户,如果给定帐户有多个订阅,则可能会返回 JSON 数组,然后查询哪个帐户是默认订阅。 它还演示了查询非默认订阅的帐户。 这些查询基于之前学到的内容来筛选和设置结果的格式。 最后,最终查询演示如何将查询结果存储在变量中。

az account list
az account list --query "[?isDefault]" # Returns the default subscription
az account list --query "[?isDefault]" -o table # Returns the default subscription as a table
az account list --query "[?isDefault].[name,id]" # Returns the name and id of the default subscription
az account list --query "[?isDefault].[name,id]" -o table # Returns the name and id of the default subscription as a table
az account list --query "[?isDefault].{SubscriptionName: name, SubscriptionId: id}" -o table # Returns the name and id of the default subscription as a table with friendly names

az account list --query "[?isDefault == \`false\`]" # Returns all non-default subscriptions, if any
az account list --query "[?isDefault == \`false\`].name" -o table # Returns all non-default subscriptions, if any, as a table

az account list --query "[?isDefault].id" -o tsv # Returns the subscription id without quotation marks
subscriptionId="$(az account list --query "[?isDefault].id" -o tsv)" # Captures the subscription id as a variable.
echo $subscriptionId # Returns the contents of the variable.
az account list --query "[? contains(name, 'Test')].id" -o tsv # Returns the subscription id of a non-default subscription containing the substring 'Test'
subscriptionId="$(az account list --query "[? contains(name, 'Test')].id" -o tsv) # Captures the subscription id as a variable. 
az account set -s $subscriptionId # Sets the current active subscription

使用变量和随机化创建对象

设置用于后续命令的随机值

通过设置和使用随机值在变量中使用,可以多次运行脚本,而不会发生命名冲突。 发生命名冲突的原因是一个值在整个服务中必须是唯一的,或者因为删除的对象仍然存在于 Azure 中,直到删除过程完成。

$RANDOM 是一个 bash 函数(而不是常量),它返回随机有符号 16 位整数(从 0 到 32767)。 该 let 命令是用于计算算术表达式的内置 Bash 命令。 使用以下命令可创建一个足够唯一的值,以用于大多数目的。

let "randomIdentifier=$RANDOM*$RANDOM"

使用空格和引号

空格用于分隔命令、选项和参数。 使用引号告知 Bash shell 忽略所有特殊字符,其中空格是特殊字符。 在 Bash shell 看到第一个引号时,它会忽略特殊字符,直到结束引号。 但是,有时你希望 Bash shell 分析某些特殊字符,例如美元符号、背引号和反斜杠。 对于此方案,请使用双引号。

以下命令使用 az group create 命令来说明单引号和双引号的使用。 在处理变量和创建对象时,这些命令用于处理空格和评估特殊字符。

resourceGroup='msdocs-learn-bash-$randomIdentifier'
echo $resourceGroup # The $ is ignored in the creation of the $resourceGroup variable
resourceGroup="msdocs-learn-bash-$randomIdentifier"
echo $resourceGroup # The $randomIdentifier is evaluated when defining the $resourceGroup variable
___location="East US" # The space is ignored when defining the $___location variable
echo The value of the ___location variable is $___location # The value of the $___location variable is evaluated
echo "The value of the ___location variable is $___location" # The value of the $___location variable is evaluated
echo "The value of the ___location variable is \$___location" # The value of the $___location variable is not evaluated
echo 'The value of the ___location variable is $___location' # The value of the $___location variable is not evaluated
az group create --name $resourceGroup --___location $___location # Notice that the space in the $___location variable is not ignored and the command fails as it treats the value after the space as a new command 
az group create --name $resourceGroup --___location "$___location" # Notice that the space in the $___location variable is ignored and the ___location argument accepts the entire string as the value 

在 JSON 字典输出中,查看已创建的资源组的属性。

使用 If Then Else 确定变量是否为 null

若要评估字符串,请使用!=,要评估数字,请使用-ne。 以下 If Then Else 语句评估是否已设置$resourceGroup变量。 如果是,则返回变量的值。 如果没有,则设置变量。

if [ $resourceGroup != '' ]; then
   echo $resourceGroup
else
   resourceGroup="msdocs-learn-bash-$randomIdentifier"
fi

使用 If Then 创建或删除资源组

仅当具有指定名称的资源组不存在时,以下脚本才会创建新的资源组。

if [ $(az group exists --name $resourceGroup) = false ]; then 
   az group create --name $resourceGroup --___location "$___location" 
else
   echo $resourceGroup
fi

如果已存在具有指定名称的新资源组,则以下脚本将删除现有资源组。 可以使用 --no-wait 参数返回控件,而无需等待命令完成。 但是,对于本文,我们希望等待资源组被删除,然后再继续。 有关异步作的详细信息,请参阅 有关成功使用 Azure CLI 的提示 - 异步作。 我们演示了本文末尾的参数用法 --no-wait

if [ $(az group exists --name $resourceGroup) = true ]; then 
   az group delete --name $resourceGroup -y # --no-wait
else
   echo The $resourceGroup resource group does not exist
fi

使用 "Grep" 来确定资源组是否存在。如果资源组不存在,请创建资源组。

以下命令使用管道将 az group list 命令的输出传递给 grep 命令。 如果指定的资源组不存在,该命令将使用以前定义的变量创建资源组。

az group list --output tsv | grep $resourceGroup -q || az group create --name $resourceGroup --___location "$___location"

使用 CASE 语句确定资源组是否存在,如果资源组不存在,则创建资源组

仅当具有指定名称的资源组不存在时,以下 CASE 语句才会创建一个新资源组。 如果存在具有指定名称的资源组,CASE 语句将回显该资源组存在。

var=$(az group list --query "[? contains(name, '$resourceGroup')].name" --output tsv)
case $resourceGroup in
$var)
echo The $resourceGroup resource group already exists.;;
*)
az group create --name $resourceGroup --___location "$___location";;
esac

使用for循环和查询数组

在本文中的本节中,我们将创建一个存储帐户,然后使用循环来创建 Blob 和容器。 我们还演示了查询 JSON 数组和使用环境变量。

创建存储帐户

以下命令使用 az storage account create 命令创建在创建存储容器时使用的存储帐户。

storageAccount="learnbash$randomIdentifier"
az storage account create --name $storageAccount --___location "$___location" --resource-group $resourceGroup --sku Standard_LRS --encryption-services blob

获取存储帐户密钥

以下命令使用 az storage account keys list 命令返回存储帐户密钥值。 然后,我们将键值存储在变量中,以便在创建存储容器时使用。

az storage account keys list --resource-group $resourceGroup --account-name $storageAccount --query "[].value" -o tsv # returns both storage account key values

az storage account keys list --resource-group $resourceGroup --account-name $storageAccount --query "[0].value" -o tsv # returns a single storage account key value

accountKey=$(az storage account keys list --resource-group $resourceGroup --account-name $storageAccount --query "[0].value" -o tsv)

echo $accountKey

创建存储容器

首先使用 az storage container create 创建单个存储容器,然后使用 az storage container list 查询所创建容器的名称。

container="learningbash"
az storage container create --account-name $storageAccount --account-key $accountKey --name $container

az storage container list --account-name $storageAccount --account-key $accountKey --query [].name

将数据上传到容器

以下脚本使用 for 循环创建三个示例文件。

for i in `seq 1 3`; do
    echo $randomIdentifier > container_size_sample_file_$i.txt
done

以下脚本使用 az storage blob upload-batch 命令将 blob 上传到存储容器。

az storage blob upload-batch \
    --pattern "container_size_sample_file_*.txt" \
    --source . \
    --destination $container \
    --account-key $accountKey \
    --account-name $storageAccount

以下脚本使用 az storage blob list 命令列出容器中的 blob。

az storage blob list \
    --container-name $container \
    --account-key $accountKey \
    --account-name $storageAccount \
    --query "[].name"

以下脚本显示存储容器中的总字节数。

bytes=`az storage blob list \
    --container-name $container \
    --account-key $accountKey \
    --account-name $storageAccount \
    --query "[*].[properties.contentLength]" \
    --output tsv | paste -s -d+ | bc`

echo "Total bytes in container: $bytes"
echo $bytes

使用循环创建多个容器

接下来,我们使用循环创建多个容器,演示了编写循环的几种方法。

for i in `seq 1 4`; do 
az storage container create --account-name $storageAccount --account-key $accountKey --name learnbash-$i
done

for value in {5..8}
for (( i=5; i<10; i++));
do
az storage container create --account-name $storageAccount --account-key $accountKey --name learnbash-$i
done

az storage container list --account-name $storageAccount --account-key $accountKey --query [].name

使用 EXPORT 定义环境变量

在前面的存储容器脚本中,我们为每个命令指定了帐户名称和帐户密钥。 相反,可以使用相应的环境变量存储身份验证凭据: AZURE_STORAGE_ACCOUNTAZURE_STORAGE_KEY。 若要执行此作,请使用 EXPORT。

export AZURE_STORAGE_ACCOUNT=$storageAccount
export AZURE_STORAGE_KEY=$accountKey
az storage container list # Uses the environment variables to display the list of containers.

以下脚本创建元数据字符串,然后使用 az storage container metadata update 命令再次使用该字符串更新容器。

metadata="key=value pie=delicious" # Define metadata
az storage container metadata update \
    --name $container \
    --metadata $metadata # Update the metadata
az storage container metadata show \
    --name $containerName # Show the metadata

以下命令使用 az storage container delete 命令删除单个命名容器,然后在循环中删除多个容器。

az storage container delete \
    --name $container

获取包含特定前缀的容器列表,并将结果存储到变量中。

containerPrefix="learnbash"
containerList=$(az storage container list \
    --query "[].name" \
    --prefix $containerPrefix \
    --output tsv)

使用 --prefix 参数删除循环中的容器列表。

for row in $containerList
do
    tmpName=$(echo $row | sed -e 's/\r//g')
    az storage container delete \
    --name $tmpName 
done

错误处理

若要在命令返回非零状态时立即退出脚本,请运行以下命令:

set -e

有关设置 shell 选项和其他帮助的详细信息,请运行以下命令:

help set
help help

清理资源

完成本文后,请删除资源组及其中的所有资源。 使用 --no-wait 参数。

if [ $(az group exists --name $resourceGroup) = true ]; then 
   az group delete --name $resourceGroup -y  --no-wait
else
   echo The $resourceGroup resource group does not exist
fi

另请参阅