查询 Azure CLI 命令输出
Azure CLI 使用 --query
参数针对命令的结果执行 JMESPath 查询。 JMESPath 是用于 JSON 的查询语言,提供在 CLI 输出中选择和修改数据的功能。 在进行任何显示格式化操作之前,先针对 JSON 输出执行查询。
Azure CLI 中的所有命令均支持 --query
参数。 本文通过一系列简单的小示例介绍了如何使用 JMESPath 的功能。
字典和列表 CLI 结果
即使是在使用 JSON 之外的输出格式的时候,也会先将 CLI 命令结果作为适合查询的 JSON 进行处理。 CLI 结果为 JSON 数组或字典。 数组是可以进行索引的对象的序列,字典是通过密钥进行访问的无序对象。 可以返回多个对象的命令会返回一个数组,而始终只返回单个对象的命令则返回字典。
获取字典中的属性
处理字典结果时,可以只使用密钥来访问顶级属性。 .
(子表达式) 字符用于访问嵌套字典的属性。 在介绍查询之前,请看看 az vm show
命令的未修改输出:
az vm show -g QueryDemo -n TestVM -o json
此命令将输出字典。 省略了一些内容。
{
"additionalCapabilities": null,
"availabilitySet": null,
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": true,
"storageUri": "https://xxxxxx.blob.core.chinacloudapi.cn/"
}
},
...
"osProfile": {
"adminPassword": null,
"adminUsername": "azureuser",
"allowExtensionOperations": true,
"computerName": "TestVM",
"customData": null,
"linuxConfiguration": {
"disablePasswordAuthentication": true,
"provisionVmAgent": true,
"ssh": {
"publicKeys": [
{
"keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMobZNJTqgjWn/IB5xlilvE4Y+BMYpqkDnGRUcA0g9BYPgrGSQquCES37v2e3JmpfDPHFsaR+CPKlVr2GoVJMMHeRcMJhj50ZWq0hAnkJBhlZVWy8S7dwdGAqPyPmWM2iJDCVMVrLITAJCno47O4Ees7RCH6ku7kU86b1NOanvrNwqTHr14wtnLhgZ0gQ5GV1oLWvMEVg1YFMIgPRkTsSQKWCG5lLqQ45aU/4NMJoUxGyJTL9i8YxMavaB1Z2npfTQDQo9+womZ7SXzHaIWC858gWNl9e5UFyHDnTEDc14hKkf1CqnGJVcCJkmSfmrrHk/CkmF0ZT3whTHO1DhJTtV stramer@contoso",
"path": "/home/azureuser/.ssh/authorized_keys"
}
]
}
},
"secrets": [],
"windowsConfiguration": null
},
....
}
以下命令通过添加查询获取经授权可以连接到 VM 的 SSH 公钥:
az vm show -g QueryDemo -n TestVM --query osProfile.linuxConfiguration.ssh.publicKeys -o json
[
{
"keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMobZNJTqgjWn/IB5xlilvE4Y+BMYpqkDnGRUcA0g9BYPgrGSQquCES37v2e3JmpfDPHFsaR+CPKlVr2GoVJMMHeRcMJhj50ZWq0hAnkJBhlZVWy8S7dwdGAqPyPmWM2iJDCVMVrLITAJCno47O4Ees7RCH6ku7kU86b1NOanvrNwqTHr14wtnLhgZ0gQ5GV1oLWvMEVg1YFMIgPRkTsSQKWCG5lLqQ45aU/4NMJoUxGyJTL9i8YxMavaB1Z2npfTQDQo9+womZ7SXzHaIWC858gWNl9e5UFyHDnTEDc14hKkf1CqnGJVcCJkmSfmrrHk/CkmF0ZT3whTHO1DhJTtV stramer@contoso",
"path": "/home/azureuser/.ssh/authorized_keys"
}
]
获取单个值
常见的情况是你需要通过 CLI 命令仅获取_一个_值,如 Azure 资源 ID、资源名称、用户名或密码。 在这种情况下,你通常还想要将该值存储在本地环境变量中。 若要获取的单个属性,首先请确保通过查询仅获取一个属性。 修改最后一个示例,以便仅获取管理员用户名:
az vm show -g QueryDemo -n TestVM --query 'osProfile.adminUsername' -o json
"azureuser"
此值看上去像有效的单个值,但请注意,"
字符作为输出的一部分返回。 这表示该对象是一个 JSON 字符串。 务必要注意,当直接将此值作为命令输出分配给环境变量时,shell 可能__无法__解释引号:
USER=$(az vm show -g QueryDemo -n TestVM --query 'osProfile.adminUsername' -o json)
echo $USER
"azureuser"
几乎可以肯定这不是你希望的。 在这种情况下,你需要使用一种不会使用类型信息将返回值括起来的输出格式。 CLI 为实现此目的而提供的最佳输出选项是 tsv
(制表符分隔值)。 具体而言,当检索某个只能是单值(不是字典或列表)的值时,tsv
输出保证不带引号。
az vm show -g QueryDemo -n TestVM --query 'osProfile.adminUsername' -o tsv
azureuser
有关 tsv
输出格式的详细信息,请参阅输出格式 - TSV 输出格式
获取多个值
若要获取多个属性,请将表达式以逗号分隔列表的形式置于方括号 [ ]
(多选列表)中。 若要一次获取包括 VM 名称、管理员用户和 SSH 密钥在内的所有内容,请使用以下命令:
az vm show -g QueryDemo -n TestVM --query '[name, osProfile.adminUsername, osProfile.linuxConfiguration.ssh.publicKeys[0].keyData]' -o json
[
"TestVM",
"azureuser",
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMobZNJTqgjWn/IB5xlilvE4Y+BMYpqkDnGRUcA0g9BYPgrGSQquCES37v2e3JmpfDPHFsaR+CPKlVr2GoVJMMHeRcMJhj50ZWq0hAnkJBhlZVWy8S7dwdGAqPyPmWM2iJDCVMVrLITAJCno47O4Ees7RCH6ku7kU86b1NOanvrNwqTHr14wtnLhgZ0gQ5GV1oLWvMEVg1YFMIgPRkTsSQKWCG5lLqQ45aU/4NMJoUxGyJTL9i8YxMavaB1Z2npfTQDQo9+womZ7SXzHaIWC858gWNl9e5UFyHDnTEDc14hKkf1CqnGJVcCJkmSfmrrHk/CkmF0ZT3whTHO1DhJTtV stramer@contoso"
]
这些值列在结果数组中,其顺序与在查询中提供这些值时的顺序一样。 由于结果为数组,因此没有与结果关联的密钥。
重命名查询中的属性
若要在查询多个值时获取字典而非数组,请使用 { }
(多选哈希)运算符:
多选哈希的格式为 {displayName:JMESPathExpression, ...}
。
displayName
将是在输出中显示的字符串,JMESPathExpression
是要求值的 JMESPath 表达式。 修改最后一部分的示例时,可以将多选列表更改为哈希:
az vm show -g QueryDemo -n TestVM --query '{VMName:name, admin:osProfile.adminUsername, sshKey:osProfile.linuxConfiguration.ssh.publicKeys[0].keyData }' -o json
{
"VMName": "TestVM",
"admin": "azureuser",
"ssh-key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMobZNJTqgjWn/IB5xlilvE4Y+BMYpqkDnGRUcA0g9BYPgrGSQquCES37v2e3JmpfDPHFsaR+CPKlVr2GoVJMMHeRcMJhj50ZWq0hAnkJBhlZVWy8S7dwdGAqPyPmWM2iJDCVMVrLITAJCno47O4Ees7RCH6ku7kU86b1NOanvrNwqTHr14wtnLhgZ0gQ5GV1oLWvMEVg1YFMIgPRkTsSQKWCG5lLqQ45aU/4NMJoUxGyJTL9i8YxMavaB1Z2npfTQDQo9+womZ7SXzHaIWC858gWNl9e5UFyHDnTEDc14hKkf1CqnGJVcCJkmSfmrrHk/CkmF0ZT3whTHO1DhJTtV stramer@contoso"
}
获取数组中的属性
数组没有自己的属性,但可以对数组进行索引。 此功能显示在表达式为 publicKeys[0]
的上一示例中,该表达式获取 publicKeys
数组的第一个元素。 无法保证 CLI 输出是有序的,因此请避免使用索引操作,除非你对顺序很确定,或者不在意获取什么元素。 若要访问数组中元素的属性,请执行下述两个操作中的一个:平展和筛选。 本部分介绍如何平展数组。
平展数组的操作通过 []
JMESPath 运算符来完成。 []
运算符之后的所有表达式都应用到当前数组中的每个元素。
如果 []
出现在查询的开头,它会平展 CLI 命令结果。 az vm list
的结果可以通过此功能来检查。
若要获取资源组中每个 VM 的名称、OS 和管理员名称,请执行以下命令:
az vm list -g QueryDemo --query '[].{Name:name, OS:storageProfile.osDisk.osType, admin:osProfile.adminUsername}' -o json
[
{
"Name": "Test-2",
"OS": "Linux",
"admin": "sttramer"
},
{
"Name": "TestVM",
"OS": "Linux",
"admin": "azureuser"
},
{
"Name": "WinTest",
"OS": "Windows",
"admin": "winadmin"
}
]
与 --output table
输出格式组合使用时,列名会与多选哈希的 displayKey
值匹配:
az vm list -g QueryDemo --query '[].{Name:name, OS:storageProfile.osDisk.osType, Admin:osProfile.adminUsername}' --output table
Name OS Admin
------- ------- ---------
Test-2 Linux sttramer
TestVM Linux azureuser
WinTest Windows winadmin
Note
某些键已筛选掉,未在表视图中输出。 这些键为 id
、type
和 etag
。 若要查看这些值,可以在多选哈希中更改键名。
az vm show -g QueryDemo -n TestVM --query "{objectID:id}" -o table
任何数组都可以平展,不仅仅是命令返回的顶级结果。 在上一部分,使用了表达式 osProfile.linuxConfiguration.ssh.publicKeys[0].keyData
来获取用于登录的 SSH 公钥。 若要获取每个 SSH 公钥,可以改将表达式编写为 osProfile.linuxConfiguration.ssh.publicKeys[].keyData
。
以下查询表达式平展 osProfile.linuxConfiguration.ssh.publicKeys
数组,然后在每个元素上运行 keyData
表达式:
az vm show -g QueryDemo -n TestVM --query '{VMName:name, admin:osProfile.adminUsername, sshKeys:osProfile.linuxConfiguration.ssh.publicKeys[].keyData }' -o json
{
"VMName": "TestVM",
"admin": "azureuser",
"sshKeys": [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMobZNJTqgjWn/IB5xlilvE4Y+BMYpqkDnGRUcA0g9BYPgrGSQquCES37v2e3JmpfDPHFsaR+CPKlVr2GoVJMMHeRcMJhj50ZWq0hAnkJBhlZVWy8S7dwdGAqPyPmWM2iJDCVMVrLITAJCno47O4Ees7RCH6ku7kU86b1NOanvrNwqTHr14wtnLhgZ0gQ5GV1oLWvMEVg1YFMIgPRkTsSQKWCG5lLqQ45aU/4NMJoUxGyJTL9i8YxMavaB1Z2npfTQDQo9+womZ7SXzHaIWC858gWNl9e5UFyHDnTEDc14hKkf1CqnGJVcCJkmSfmrrHk/CkmF0ZT3whTHO1DhJTtV stramer@contoso\n"
]
}
筛选数组
另一项用于从数组获取数据的操作是筛选。 筛选操作通过 [?...]
JMESPath 运算符来完成。
此运算符采用谓词作为其内容。 谓词是指其求值结果可能为 true
或 false
的任何语句。 所含谓词的求值结果为 true
的表达式包括在输出中。
JMESPath 提供标准的比较运算符和逻辑运算符。 其中包括 <
、<=
、>
、>=
、==
、!=
。 JMESPath 也支持逻辑 AND (&&
)、OR (||
) 和 NOT (!
)。 表达式可以在括号中进行分组,因此可以形成更复杂的谓词表达式。 有关谓词和逻辑运算的完整详细信息,请参阅 JMESPath specification(JMESPath 规范)。
在上一部分,我们平展了一个数组,目的是获取资源组中所有 VM 的完整列表。 可以通过筛选器将以下输出限制为 Linux VM:
az vm list -g QueryDemo --query "[?storageProfile.osDisk.osType=='Linux'].{Name:name, admin:osProfile.adminUsername}" --output table
Name Admin
------ ---------
Test-2 sttramer
TestVM azureuser
Important
在 JMESPath 中,字符串始终带单引号 ('
)。 如果在筛选器谓词中使用双引号作为字符串的一部分,则会获得空的输出。
JMESPath 也有内置函数,可以用来进行筛选。 contains(string, substring)
就是这样的一个函数,用于查看字符串是否包含子字符串。 在调用函数之前,会对表达式求值,因此第一个参数可以是完整的 JMESPath 表达式。 下一示例查找使用 SSD 存储作为其 OS 磁盘的所有 VM:
az vm list -g QueryDemo --query "[?contains(storageProfile.osDisk.managedDisk.storageAccountType,'SSD')].{Name:name, Storage:storageProfile.osDisk.managedDisk.storageAccountType}" -o json
[
{
"Name": "TestVM",
"Storage": "StandardSSD_LRS"
},
{
"Name": "WinTest",
"Storage": "StandardSSD_LRS"
}
]
此查询有点长。 storageProfile.osDisk.managedDisk.storageAccountType
键提到两次,在输出中重新生成了键。 若要将其缩短,一种方式是在平展并选择数据后应用筛选器。
az vm list -g QueryDemo --query "[].{Name:name, Storage:storageProfile.osDisk.managedDisk.storageAccountType}[?contains(Storage,'SSD')]" -o json
[
{
"Name": "TestVM",
"Storage": "StandardSSD_LRS"
},
{
"Name": "WinTest",
"Storage": "StandardSSD_LRS"
}
]
对于大型数组,在选择数据之前先应用筛选器可能速度更快。
若要获取函数的完整列表,请参阅 JMESPath specification - Built-in Functions(JMESPath 规范 - 内置函数)。
更改输出
JMESPath 函数还有另一用途,即根据查询结果进行运算。 任何返回非布尔值的函数都会改变表达式的结果。
例如,可以通过 sort_by(array, &sort_expression)
按属性值对数据排序。 对于应该在后面作为函数的一部分求值的表达式,JMESPath 使用特殊运算符 &
。 下一示例演示如何按 OS 磁盘大小对 VM 列表排序:
az vm list -g QueryDemo --query "sort_by([].{Name:name, Size:storageProfile.osDisk.diskSizeGb}, &Size)" --output table
Name Size
------- ------
TestVM 30
Test-2 32
WinTest 127
若要获取函数的完整列表,请参阅 JMESPath specification - Built-in Functions(JMESPath 规范 - 内置函数)。
以交互方式试验查询
若要开始试验 JMESPath,请使用 JMESPath-terminal Python 包,它提供了用于处理查询的交互式环境。 将数据作为输入通过管道传送,然后在编辑器中编写并运行查询。
pip install jmespath-terminal
az vm list --output json | jpterm