告别”面条式”Bash 脚本:用现代框架构建 CLI 工具

告别”面条式”Bash 脚本:用现代框架构建 CLI 工具

一个让 Bash 脚本具备工程化结构的开源框架

前言:Bash 脚本的困境

每个运维工程师、DevOps 工程师都写过 Bash 脚本。

一开始只是几行自动化命令。然后需求来了——加个参数、加个选项、加个配置文件。几个月后,脚本膨胀到几百行,充斥着嵌套的 if-else、手写的参数解析、到处 source 的公共函数……

问题不在 Bash 本身,而在于我们缺少一个工程化的方式来组织 Bash 代码。

今天介绍的 RADP Bash Framework,就是为了解决这个问题而生的。

传统 Bash 脚本的痛点

1. 没有项目结构

函数和变量散落各处,全局变量冲突,逻辑和界面混杂。新人接手需要花大量时间理解代码。

2. 参数解析地狱

每个脚本都在重复实现 getopts 或手动解析参数:

# 传统方式:每个脚本都要写一遍
while [[ $# -gt 0 ]]; do
    case "$1" in
        -f|--force) force=true; shift ;;
        -e|--env) env="$2"; shift 2 ;;
        -h|--help) show_help; exit 0 ;;
        *) args+=("$1"); shift ;;
    esac
done

3. 缺乏自文档化

新成员不知道脚本支持哪些参数、参数是什么含义。只能靠口口相传或翻代码。

4. 复制粘贴式复用

需要日志功能?从其他脚本复制。需要配置解析?再复制。哪天要改,所有脚本都要同步更新。

RADP Bash Framework 的解决方案

一键创建 CLI 项目

# 安装框架
brew tap xooooooooox/radp
brew install radp-bash-framework

# 创建新项目
radp-bf new myctl
cd myctl

生成的项目结构:

myctl/
├── bin/myctl                     # 入口脚本
├── src/main/shell/
│   ├── commands/                 # 命令目录
│   │   ├── hello.sh              # myctl hello
│   │   └── version.sh            # myctl version
│   └── config/
│       └── config.yaml           # 配置文件
└── install.sh                    # 安装脚本

注解式命令定义

这是框架最强大的特性——用注释定义命令元数据:

# src/main/shell/commands/deploy.sh

# @cmd
# @desc 部署应用到指定环境
# @arg env!                   必填:目标环境 (dev/staging/prod)
# @option -f, --force         跳过确认提示
# @option -t, --tag <string>  Docker 镜像标签 (默认: latest)
# @example deploy staging
# @example deploy prod --tag v1.2.3 --force

cmd_deploy() {
    local env="$1"
    local force="${opt_force:-false}"
    local tag="${opt_tag:-latest}"
    
    if [[ "$force" != "true" ]]; then
        read -p "确认部署到 $env? [y/N] " confirm
        [[ "$confirm" != "y" ]] && exit 0
    fi
    
    radp_log_info "正在部署 $tag$env..."
    # 部署逻辑
}

框架自动解析注解,提供:

  • 自动生成帮助信息
  • 参数校验(必填/可选)
  • 选项解析(支持短选项和长选项)
  • Shell 补全(Bash/Zsh)
$ myctl deploy --help
部署应用到指定环境

Usage: myctl deploy [OPTIONS] <env>

Arguments:
  env    必填:目标环境 (dev/staging/prod)

Options:
  -f, --force         跳过确认提示
  -t, --tag <string>  Docker 镜像标签 (默认: latest)

Examples:
  myctl deploy staging
  myctl deploy prod --tag v1.2.3 --force

子命令自动发现

创建目录即创建命令组:

commands/
├── db/
│   ├── migrate.sh        # myctl db migrate
│   ├── seed.sh           # myctl db seed
│   └── backup.sh         # myctl db backup
├── k8s/
│   ├── apply.sh          # myctl k8s apply
│   └── delete.sh         # myctl k8s delete
└── deploy.sh             # myctl deploy

零配置。目录结构就是命令结构。

YAML 配置管理

支持 YAML 配置文件,自动映射为环境变量:

# config/config.yaml
radp:
  extend:
    myctl:
      api_url: https://api.example.com
      timeout: 30
      database:
        host: localhost
        port: 5432

在代码中访问:

echo "$gr_radp_extend_myctl_api_url"         # https://api.example.com
echo "$gr_radp_extend_myctl_database_host"   # localhost

支持环境变量覆盖:

GX_RADP_EXTEND_MYCTL_API_URL=http://localhost:8080 myctl run

内置工具库

框架提供常用的工具函数:

# 结构化日志
radp_log_info "开始部署"
radp_log_warn "配置文件缺失,使用默认值"
radp_log_error "连接失败"
radp_log_debug "响应: $response"

# 操作系统检测
distro=$(radp_os_get_distro_id)      # ubuntu, centos, fedora...
pm=$(radp_os_get_distro_pm)          # apt, yum, dnf...

# 包管理检测
if radp_os_is_pkg_installed "docker"; then
    echo "Docker 已安装"
fi

# 路径工具
abs_path=$(radp_io_get_path_abs "./relative/path")

完整示例:Kubernetes 部署工具

# commands/pod/restart.sh

# @cmd
# @desc 重启指定 Pod
# @arg pod!                     Pod 名称
# @option -n, --namespace <ns>  命名空间 (默认: default)
# @option --all                 重启所有匹配的 Pod
# @example pod restart api-gateway
# @example pod restart nginx -n production --all

cmd_pod_restart() {
    local pod="$1"
    local ns="${opt_namespace:-default}"
    local all="${opt_all:-false}"
    
    radp_log_info "正在重启 $ns/$pod..."
    
    if [[ "$all" == "true" ]]; then
        kubectl delete pods -n "$ns" -l "app=$pod"
    else
        kubectl delete pod -n "$ns" "$pod"
    fi
    
    radp_log_info "Pod 重启完成"
}

使用:

$ myctl pod restart api-gateway -n production
[INFO] 正在重启 production/api-gateway...
[INFO] Pod 重启完成

$ myctl pod --help
Pod 管理命令

Commands:
  restart    重启指定 Pod
  logs       查看 Pod 日志
  exec       在 Pod 中执行命令

安装方式

Homebrew(macOS/Linux)

brew tap xooooooooox/radp
brew install radp-bash-framework

脚本安装

curl -fsSL https://raw.githubusercontent.com/xooooooooox/radp-bash-framework/main/install.sh | bash

RPM 包(Fedora/RHEL/CentOS)

sudo dnf copr enable -y xooooooooox/radp
sudo dnf install -y radp-bash-framework

在 Shell 中加载框架

# 添加到 ~/.bashrc
source "$(radp-bf --print-run)"

适用场景

推荐使用:

  • 内部 DevOps 工具
  • 系统运维脚本
  • CI/CD 流水线辅助工具
  • 项目级自动化脚本
  • 任何需要结构化的 Bash CLI

可能过度的场景:

  • 50 行以下的一次性脚本
  • 无用户交互的简单自动化
  • 性能敏感的内层循环

与其他工具对比

特性传统 BashRADP Bash Framework
项目结构标准化目录
参数解析手动实现注解自动生成
帮助信息手动维护自动生成
子命令手动路由目录自动发现
配置管理各自实现YAML + 环境变量
日志echo/printf结构化日志
Shell 补全几乎没有自动生成

总结

Bash 不会消失。它预装在几乎所有 Unix 系统上,是运维和自动化的首选语言。

但”快速编写”不应该意味着”无法维护”。RADP Bash Framework 把我们在其他语言中习以为常的模式——命令发现、参数解析、配置管理——带到了 Shell 脚本世界。

让你的 Bash 脚本也具备工程化的结构。


项目地址: https://github.com/xooooooooox/radp-bash-framework

MIT 开源协议,欢迎 Star 和贡献代码!


有问题或建议?欢迎在评论区交流,或到 GitHub 提 Issue。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值