首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >基于Rust开发CLI小工具

基于Rust开发CLI小工具

原创
作者头像
用户10577234
修改2026-01-04 18:08:31
修改2026-01-04 18:08:31
1390
举报

我在学习 Rust 的过程中,一直想做一个“能解决真实问题”的小项目。日常使用 ClaudeCode 时,经常要在不同 API 之间切换:比如自建的 Anthropic 代理、智谱 Anthropic 网关等。手动改环境变量不仅麻烦,还容易在多个终端之间混淆。于是我写了一个 CLI 工具 anthropic-config,目标很明确:用一条命令完成配置切换,并把它做成可复用、可安装的 Rust CLI 项目。

环境准备(安装与学习入口)

安装 Rust:

安装后确认工具链可用:

代码语言:javascript
复制
rustc -V
cargo -V

学习资料入口:

项目结构与核心实现(代码集中展示)

先明确功能边界,避免“越写越偏”。本项目只做三件事:设置 API 配置、切换预设网关、查看当前配置。功能不大,但刚好覆盖 Rust CLI 的完整链路:参数解析、交互输入、环境变量、跨平台处理、安装与发布。

1)初始化项目并拆分模块

代码语言:javascript
复制
cargo new anthropic-config
cd anthropic-config

拆分结构如下:

代码语言:javascript
复制
src/
├── main.rs       # 程序入口,负责分发命令
├── cli.rs        # CLI 参数解析与帮助信息
├── handlers.rs   # 命令业务逻辑
├── env.rs        # 环境变量设置与持久化
└── utils.rs      # 输入读取、默认值、脱敏处理

这样拆分的原因是:入口保持干净、业务集中、跨平台逻辑独立、工具函数可复用。

2)CLI 参数解析(cli.rs)

代码语言:javascript
复制
use std::env;
​
pub enum Command {
    Custom,
    BigModel,
    Show,
    Unknown,
}
​
pub fn parse_command() -> Command {
    let args: Vec<String> = env::args().collect();
​
    if args.len() < 2 {
        return Command::Unknown;
    }
​
    match args[1].as_str() {
        "custom" => Command::Custom,
        "big_model" => Command::BigModel,
        "show" => Command::Show,
        _ => Command::Unknown,
    }
}

用枚举做命令分发,避免全项目散落字符串,也方便扩展新子命令。

3)程序入口分发(main.rs)

代码语言:javascript
复制
mod cli;
mod env;
mod handlers;
mod utils;
​
use cli::Command;
​
fn main() {
    let cmd = cli::parse_command();
​
    match cmd {
        Command::Custom => handlers::handle_custom(),
        Command::BigModel => handlers::handle_big_model(),
        Command::Show => handlers::handle_show(),
        Command::Unknown => cli::print_usage(),
    }
}

入口只做分发,保持清晰,后续新增命令也不会乱。

4)业务逻辑与输入校验(handlers.rs + utils.rs)

代码语言:javascript
复制
use crate::env::confirm_and_apply;
use crate::utils::{mask, read_required, read_with_default};
​
pub fn handle_big_model() {
    println!("Zhihu AI Big Model configuration\n");
​
    let default_url = "https://open.bigmodel.cn/api/anthropic";
    let base_url = read_with_default(
        &format!("ANTHROPIC_BASE_URL [{}]: ", default_url),
        default_url,
    );
​
    let token = read_required("ANTHROPIC_AUTH_TOKEN (required): ");
​
    confirm_and_apply(&base_url, &token);
}

配合 read_required 做输入校验,避免空值写入:

代码语言:javascript
复制
pub fn read_required(prompt: &str) -> String {
    loop {
        let v = read_line(prompt);
        if !v.is_empty() {
            return v;
        }
        println!("Value required.\n");
    }
}

5)环境变量持久化(env.rs)

核心目标是“当前进程立即生效 + 写入系统保证下次可用”。Windows 用 setx,macOS/Linux 写 ~/.bashrc

代码语言:javascript
复制
pub fn persist_env(key: &str, value: &str) -> Result<(), String> {
    if cfg!(target_os = "windows") {
        Command::new("cmd")
            .args(["/C", "setx", key, value])
            .status()
            .map_err(|e| e.to_string())
            .and_then(|s| {
                if s.success() { Ok(()) } else { Err("setx failed".into()) }
            })
    } else {
        let home = std::env::var("HOME").map_err(|_| "HOME not set".to_string())?;
        let profile = format!("{}/.bashrc", home);
​
        let mut f = OpenOptions::new()
            .create(true)
            .append(true)
            .open(&profile)
            .map_err(|e| e.to_string())?;
​
        writeln!(f, "\nexport {}=\"{}\"", key, value).map_err(|e| e.to_string())
    }
}

另外增加预览与确认,并对 token 做脱敏显示,避免误操作和泄露风险。

打包与使用(完整流程)

开发期运行:

代码语言:javascript
复制
cargo run -- show

发布版构建:

代码语言:javascript
复制
cargo build --release

推荐安装方式:

代码语言:javascript
复制
cargo install --path .

下面是打包的过程,它主要干了这些事情

  • 检查当前目录是不是 Cargo 项目(Cargo.toml + main.rs
  • 编译(等同于 cargo build --release
  • 复制可执行文件~/.cargo/bin(进 PATH)

安装后可直接使用:

代码语言:javascript
复制
anthropic-config show
anthropic-config custom
anthropic-config big_model

我平时用 big_model 作为默认入口,切换之后只需要重开终端即可生效,不必每次进入系统环境变量里手动修改。

跨平台与常见问题(合并说明更清晰)

跨平台注意事项:

  • Windows:setx 只影响未来的终端,需要重开终端。
  • macOS/Linux:写入 ~/.bashrc 后需 source ~/.bashrc 或重开终端。
  • zsh 用户:可将写入路径改为 ~/.zshrc

常见问题排查:

  • setx 失败:可能权限不足或参数过长,失败后可按提示手动设置。
  • HOME 为空:某些简化环境可能没有 HOME,建议手动指定配置文件路径。
  • token 外泄风险:已在 mask() 做脱敏显示,避免终端日志泄露。

总结与扩展方向

这个 CLI 工具很小,但覆盖了 Rust 学习的多个关键点:模块化组织、CLI 参数解析、交互式输入校验、跨平台环境变量持久化、打包与安装流程。重点不是功能多,而是把完整链路打通,用真实需求驱动学习,效果远比刷语法要好。

未来可扩展方向:

  • 引入 clap 优化参数解析
  • 支持多 profile(dev/prod/test)
  • 用配置文件代替环境变量

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 环境准备(安装与学习入口)
  • 项目结构与核心实现(代码集中展示)
  • 打包与使用(完整流程)
  • 跨平台与常见问题(合并说明更清晰)
  • 总结与扩展方向
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档