你当前正在访问 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 Shell本地安装的 Azure CLI 启动 Bash。 本文假设你使用 Azure Cloud Shell 或在 docker 容器中本地运行 Azure CLI 来运行 Bash。

查询字典结果

始终仅返回单个对象的命令将返回一个 JSON 字典。 字典是使用键访问的无序对象。 对于本文,我们将首先使用 Account Show 命令查询 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,因此 az account list 命令的 "[?isDefault]" 查询语法返回当前默认订阅。 若要获取 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 循环和查询数组

在本文的这一部分中,我们将创建一个存储帐户,然后使用 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

另请参阅