oh-my-zsh azure 插件详解:az CLI 补全、订阅管理与提示符中的 Azure 状态显示
oh-my-zsh 的 azure 插件围绕 Azure CLI(az)提供三类能力:加载 az 命令的补全脚本、提供切换与查看 Azure 订阅的快捷命令(azss/azgs/az_subscriptions),以及在提示符中通过 azure_prompt_info 函数显示当前默认订阅。读完本文,你可以在 ~/.zshrc 中正确启用该插件、理解其订阅命令的实现细节,并将当前 Azure 订阅显示到 RPROMPT 中,同时了解其依赖 jq 与补全脚本定位的底层机制。
插件定位与启用方式
azure 插件文档 说明,该插件为 Azure CLI 提供补全支持,并提供管理 Azure 订阅、在提示符中显示订阅的实用工具。启用方式与其他 oh-my-zsh 插件一致:在 ~/.zshrc 的 plugins 数组中加入 azure:
plugins=(... azure)
仓库自带的配置模板 templates/zshrc.zsh-template 和精简模板 templates/minimal.zshrc 中 plugins 数组均默认只含 git(plugins=(git)),启用 azure 插件时需要手动在该数组末尾追加 azure。
插件全部实现集中在 plugins/azure/azure.plugin.zsh 一个文件中,可分为三块:订阅管理命令、提示符函数、az 补全脚本加载逻辑。
三个核心订阅命令
README 的 "Plugin commands" 一节列出了三个命令,下面结合 azure.plugin.zsh 的源码逐一说明其真实行为。
az_subscriptions:列出可用订阅
az_subscriptions 用于列出 AZURE_CONFIG_DIR(默认 ~/.azure/)中可用的订阅,同时为 azss 函数提供补全数据源。源码实现为:
function az_subscriptions() {
az account list --all --output tsv --query '[*].name' 2> /dev/null
}
从源码看,它实际执行的是 az account list --all --output tsv --query '[*].name':--all 会列出所有订阅(包括非已登录目录下的),--output tsv 输出制表符分隔格式,--query 用 JMESPath 只保留 name 字段,2> /dev/null 则静默了 Azure CLI 常见的 stderr 告警。
其配套补全函数是:
function _az_subscriptions() {
reply=($(az_subscriptions))
}
compctl -K _az_subscriptions azss
compctl -K 将 azss 命令的补全回调指向 _az_subscriptions,每次触发补全时调用 az_subscriptions 并把订阅名填入 reply 数组。
azgs:获取当前订阅
azgs 读取当前激活的订阅值。文档描述为 "gets the current value of $azure_subscription",而源码实现是直接调用 Azure CLI:
function azgs() {
az account show --output tsv --query 'name' 2>/dev/null
}
即执行 az account show 并用 JMESPath 查询 name 字段。注意这一点在插件内部有实际影响:azure_prompt_info 的注释明确写道 "azgs is too expensive, if we have jq, we enable the prompt"——因为 azgs 每次都要启动一次 az 进程,代价较高,所以提示符函数没有直接复用它,而是改用本地文件解析(见下文)。
azss:设置当前订阅
azss 用于设置 $azure_subscription,源码中其实是一个别名:
# AZ Subscription Selection
alias azss="az account set --subscription"
执行 azss 等价于 az account set --subscription,由于前面对 azss 注册了 compctl 补全,输入 azss <Tab> 即可从 az_subscriptions 返回的订阅列表中选取,无需手打订阅名。
提示符集成:azure_prompt_info 与 jq 依赖
插件文档 "Theme" 一节说明,azure 插件创建了 azure_prompt_info 函数,供主题在提示符中显示当前订阅,其源码位于 azure.plugin.zsh 第 20-26 行:
# Azure prompt
function azure_prompt_info() {
[[ ! -f "${AZURE_CONFIG_DIR:-$HOME/.azure}/azureProfile.json" ]] && return
# azgs is too expensive, if we have jq, we enable the prompt
(( $+commands[jq] )) || return 1
azgs=$(jq -r '.subscriptions[] | select(.isDefault==true) .name' "${AZURE_CONFIG_DIR:-$HOME/.azure}/azureProfile.json")
echo "${ZSH_THEME_AZURE_PREFIX:=<az:}${azgs}${ZSH_THEME_AZURE_SUFFIX:=>}"
}
从源码可以拆解出它的执行流程与降级条件:
-
配置目录探测:先检查
${AZURE_CONFIG_DIR:-$HOME/.azure}/azureProfile.json是否存在,不存在则静默返回(提示符不显示任何内容)。这与 README 中的 NOTE 一致:Azure CLI 把当前激活订阅的状态保存在azureProfile.json中,因此提示符命令依赖该文件。 -
jq 检查:
(( $+commands[jq] )) || return 1是 oh-my-zsh 判断外部命令是否存在的惯用写法($+commands[jq]在jq位于 PATH 中时为 1)。如果系统没有安装jq,函数返回 1,提示符显示为空——README 明确警告 "If jq is not in the path the prompt will show nothing"。 -
JSON 解析:用
jq -r '.subscriptions[] | select(.isDefault==true) .name'从azureProfile.json中筛选isDefault == true的订阅并取出name,完全在本地完成,不启动az进程,这也是注释中 "azgs is too expensive" 的原因。 -
前后缀拼接:输出格式由两个变量控制,使用 zsh 的
:=赋值展开语法提供默认值:ZSH_THEME_AZURE_PREFIX:订阅名前的前缀,默认<az:;ZSH_THEME_AZURE_SUFFIX:订阅名后的后缀,默认>。
默认输出形如
<az:my-subscription>。需要注意一个文档与源码的差异:README 中将后缀变量写作ZSH_THEME_azure_SUFFIX(azure 小写),而 azure.plugin.zsh 第 25 行 实际读取的是ZSH_THEME_AZURE_SUFFIX(全大写 AZURE),自定义该变量时应以源码为准。
文档给出的接入方式是:
RPROMPT='$(azure_prompt_info)'
当前仓库的 themes/ 目录下没有任何内置主题直接调用 azure_prompt_info(检索全部 .zsh-theme 文件无匹配),因此该函数需要用户在自己的主题或 ~/.zshrc 中手动接入。
未启用插件时的兜底:dummy 实现
oh-my-zsh 在 lib/prompt_info_functions.zsh 中为一系列 *_prompt_info 函数定义了统一的假实现(dummy implementation),azure_prompt_info 在 第 13-26 行 的函数列表中:
# Dummy implementations that return false to prevent command_not_found
# errors with themes, that implement these functions
# Real implementations will be used when the respective plugins are loaded
function chruby_prompt_info \
...
azure_prompt_info \
...
{
return 1
}
文件头注释说明了设计意图:主题可以直接无条件调用 azure_prompt_info,即使用户没有启用 azure 插件,也不会触发 command_not_found 错误——dummy 实现只是 return 1;一旦加载了 azure 插件,插件中的真实实现会覆盖这个兜底版本。这是 oh-my-zsh 主题与插件解耦的标准模式,git_prompt_info、bzr_prompt_info、nvm_prompt_info 等也遵循同样的机制(见 lib/git.zsh 等文件)。
az CLI 补全脚本的加载机制
插件的另一半职责是加载 Azure CLI 的补全脚本。azure.plugin.zsh 第 29-60 行 的查找顺序如下:
- 从
$PATH中查找:_az_zsh_completer_path="$commands[az_zsh_completer.sh]",部分发行版会把az_zsh_completer.sh放进 PATH,优先采用它。 - Homebrew 路径:若 PATH 中找不到,且检测到 Homebrew 已安装,则使用
$_brew_prefix/etc/bash_completion.d/az。这里有个性能细节,_az-homebrew-installed函数先通过[[ ${commands[brew]:t2} == bin/brew ]]判断 brew 是否装在默认位置——是的话直接从brew的完整路径裁剪出前缀(_brew_prefix="${commands[brew]:h:h}"),否则才调用一次brew --prefix。源码注释指出 "this call to brew is expensive (about 400 ms), so at least let's make it only once",即避免每次加载都付出约 400ms 的进程启动开销。 - Linux 默认路径:非 Homebrew 环境回退到
/etc/bash_completion.d/azure-cli(通过 apt 等包管理器安装的 azure-cli 通常将补全脚本放在这里)。
最终由这一行完成实际加载:
[[ -r $_az_zsh_completer_path ]] && autoload -U +X bashcompinit && bashcompinit && source $_az_zsh_completer_path
即:补全脚本文件可读时,先通过 autoload -U +X bashcompinit 初始化 bash 补全兼容层(Azure CLI 的补全脚本是 bash-completion 格式,zsh 需要 bashcompinit 才能加载它),然后 source 该脚本。加载完成后 unset _az_zsh_completer_path _brew_prefix 清理临时变量。如果所有候选路径都不存在(例如尚未安装 Azure CLI),整个条件短路,插件静默跳过补全加载而不报错。
开发环境搭建
文档 "Develop" 一节给出了在 Ubuntu 上通过 Docker 快速搭建插件开发环境的方法,先运行:
docker run -it -v $(pwd):/mnt -w /mnt ubuntu bash
再在容器内依次安装依赖、安装 oh-my-zsh 与 Azure CLI:
apt install -y curl jq zsh git vim
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
curl -sL https://aka.ms/InstallAzureCLIDeb | bash
其中 curl jq zsh git vim 里的 jq 正是提示符函数运行所必需的依赖,与上文 azure_prompt_info 的 jq 检查相呼应;最后两条命令分别安装 oh-my-zsh 框架本体和 Azure CLI,安装后即可在容器内的 zsh 中加载 azure 插件验证补全与订阅命令行为。
小结
| 能力 | 入口 | 底层实现 |
|---|---|---|
| 订阅补全数据源 | az_subscriptions |
az account list --all --output tsv --query '[*].name' |
| 获取当前订阅 | azgs |
az account show --output tsv --query 'name' |
| 设置当前订阅 | azss |
别名 az account set --subscription,注册了 compctl 补全 |
| 提示符显示订阅 | azure_prompt_info |
用 jq 本地解析 azureProfile.json,前后缀由 ZSH_THEME_AZURE_PREFIX/ZSH_THEME_AZURE_SUFFIX 控制 |
| az 命令补全 | — | 按 $PATH → Homebrew → /etc/bash_completion.d/azure-cli 顺序定位补全脚本,经 bashcompinit 加载 |
使用 azure 插件有两个硬性前提:系统安装 az CLI(订阅命令与补全都依赖它),以及安装 jq(否则提示符永远为空)。配置上只需在 plugins 数组中加入 azure,并在提示符中引用 azure_prompt_info 即可完成接入;如需自定义提示符样式,修改 ZSH_THEME_AZURE_PREFIX 与 ZSH_THEME_AZURE_SUFFIX 即可。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00