← 返回目录 > ← 返回总览

Shell语言检查工具选型与落地建议

1. 工具选型表

工具 简介 优先级 误报率 告警抑制(屏蔽)方式 适用场景
Shfmt 格式化:AST 解析,多方言+EditorConfig 必选 工具配置 本地增量、本地全量、PR增量、PR全量
ShellCheck 静态分析:600+ 规则,附修复建议 必选 行级注释、块级注释、文件级注释、工具配置 本地增量、本地全量、PR增量、PR全量
pre-commit 调度框架:声明式 YAML,依赖隔离 推荐 工具配置 本地增量、PR全量
Gitleaks 密钥检测:正则+熵分析,递归解码 推荐 行级注释、工具配置 本地增量、PR增量、PR全量、主干全量
Codespell 拼写检查:Wikipedia 常见错误字典 推荐 行级注释、工具配置 本地增量、PR增量、PR全量

2. 主流社区参考

2.1 Homebrew

Homebrew 是 macOS/Linux 包管理器,其 Shell 脚本检查实践值得借鉴。Homebrew 通过 .shellcheckrc 配置 ShellCheck 规则,在 CI 中强制执行,并针对 formula 文件的特定场景禁用部分规则(如 SC2034)。

  • 仓库地址https://github.com/Homebrew/brew (⭐ 48.9k)
  • 使用工具:ShellCheck(静态分析)、Vale(文档 lint)、EditorConfig
  • 工作流:通过 GitHub Actions 在 CI 中运行 ShellCheck;本地通过 .shellcheckrc 配置检查规则;未使用 pre-commit 框架,将检查直接放入 CI 工作流
  • 关键配置:.shellcheckrc、.vale.ini、.editorconfig、.github/workflows/
  • 借鉴价值:ShellCheck 是 Bash/zsh 生态的事实标准 linter;.shellcheckrc 可针对项目特定场景禁用部分规则;不使用 pre-commit 框架而直接放入 CI 也是可行的方案

2.2 oh-my-zsh

oh-my-zsh 是最流行的 zsh 框架,仓库以 zsh 脚本为主。oh-my-zsh 未使用专门的 Shell linter,但维护了一致的 .editorconfig,并用 Prettier 格式化工具链中的 JS 辅助脚本。

  • 仓库地址https://github.com/ohmyzsh/ohmyzsh (⭐ 188.7k)
  • 使用工具:Prettier(格式化 JS/JSON)、EditorConfig
  • 工作流:通过 GitHub Actions 运行 Prettier;仓库本身以 zsh 脚本为主,未使用专门的 Shell linter
  • 关键配置:.editorconfig、.prettierrc、.github/workflows/
  • 借鉴价值:纯 Shell 项目(如 zsh 插件/主题)通常不强制集成 ShellCheck,但维护一致的 .editorconfig 是基本要求;Prettier 用于工具链中的 JS 辅助脚本格式化

2.3 Bash-it

Bash-it 是推荐采用 pre-commit + ShellCheck + shfmt 组合的典型样本——pre-commit 提供统一入口,shfmt 处理缩进/对齐格式化,ShellCheck 做静态分析。这是社区中可复制的标准化方案。

  • 仓库地址https://github.com/Bash-it/bash-it (⭐ 15.1k)
  • 使用工具:pre-commit 框架、ShellCheck、shfmt(通过 pre-commit hooks)、EditorConfig、ack
  • 工作流:使用 pre-commit 框架统一管理本地与 CI 检查;通过 .pre-commit-config.yaml 声明 shfmt 和 shellcheck hooks;CI 复用同一配置
  • 关键配置:.pre-commit-config.yaml、.editorconfig、.ackrc、.github/workflows/
  • 借鉴价值:中等规模 Shell 项目推荐采用 pre-commit + ShellCheck + shfmt 的组合;pre-commit 提供统一入口,shfmt 处理格式化,ShellCheck 做静态分析,是社区中可复制的标准化方案

2.4 fish-shell

fish-shell 是友好的交互式 shell 实现,Shell 代码占比 21.9%、Rust 70.3%。CI 中有独立的 shellcheck job,通过 cargo xtask shellcheck 统一调用 ShellCheck 检查所有 Shell 脚本。

  • 仓库地址https://github.com/fish-shell/fish-shell (⭐ 33.9k)
  • 使用工具:ShellCheck、rustfmt、Clippy、clang-format、ruff
  • 工作流:Cargo + CMake 构建 + GitHub Actions,lint.yml 拆分为 format、shellcheck、clippy、rustdoc 多个独立 job
  • 关键配置.github/workflows/lint.yml.clang-format.rustfmt.tomlclippy.toml.editorconfig
  • 借鉴价值:展示了 Shell 项目在 CI 中以独立 job 运行 ShellCheck 的最佳实践;通过 cargo xtask 封装 ShellCheck 命令统一调用入口;多语言项目的 lint 工作流拆分策略

2.5 oh-my-bash

Oh My Bash 是 Bash 配置框架(Oh My Zsh 的 Bash 移植),纯 Shell 项目。通过 .shellcheckrc 配置 ShellCheck 规则,CI 中使用 editorconfig-checker 检查格式合规性。

  • 仓库地址https://github.com/ohmybash/oh-my-bash (⭐ 7.6k)
  • 使用工具:ShellCheck、editorconfig-checker
  • 工作流:GitHub Actions,format.yml 运行 editorconfig-checker 检查变更文件,test.yml 在 Linux/Windows/macOS 三平台矩阵运行安装测试
  • 关键配置.shellcheckrc.github/workflows/format.yml.editorconfig
  • 借鉴价值:演示了纯 Shell 项目通过 .shellcheckrc 定制 ShellCheck 规则(如针对兼容性需求禁用 SC1087);EditorConfig + editorconfig-checker 的格式约束实践;跨平台 CI 矩阵验证 Shell 框架可移植性

3. 工程配置建议

Shell 生态主流项目(Homebrew、Bash-it、oh-my-bash)以 ShellCheck + shfmt 为核心工具链,Bash-it 展示了 pre-commit + ShellCheck + shfmt 的标准化组合。工程配置以 pre-commit 为代码仓级统一调度入口,官方基础 hook 覆盖全仓文件级问题,Shell 专用的 shfmt 和 ShellCheck 通过 pre-commit hook 调用。

3.1 工程配置文件汇总

配置文件 配置内容/作用 使用场景 维护建议
.shellcheckrc 配置 ShellCheck 规则、shell 方言、排除规则 ShellCheck 检查时读取 新项目直接创建;存量项目按需调整
.editorconfig 统一脚本缩进和换行风格 编辑器保存时格式化 全仓通用,与 Shfmt 配合
.pre-commit-config.yaml 官方基础 hook、密钥检测、拼写检查、Shfmt、ShellCheck 本地提交前、PR 轻量门禁 由仓库统一维护版本;新增 hook 应说明耗时和误报处理方式
.gitignore / 工具 ignore 文件 排除构建产物、生成代码、第三方代码 本地、PR、全量检查 生成代码和 vendored 目录优先集中排除
.github/workflows/* PR 门禁、主干全量、夜间任务 PR、主干、发布前、夜间 CI 命令应尽量复用本地命令

3.2 .pre-commit-config.yaml

Shell 项目推荐以 pre-commit 作为代码仓级统一调度入口:先使用 pre-commit 官方基础 hook 覆盖全仓文件级问题,再叠加密钥检测、拼写检查,最后追加 Shell 专用的 ShfmtShellCheck。这样即使仓库后续增加 Markdown、JSON、YAML 等文件,也能保持统一的提交前检查入口。

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: trailing-whitespace # 移除行尾空白字符
      - id: end-of-file-fixer # 确保文件以换行符结尾
      - id: check-yaml # 校验 YAML 文件语法
      - id: check-json # 校验 JSON 文件语法
      - id: check-xml # 校验 XML 文件语法
      - id: check-merge-conflict # 检查未解决的合并冲突标记
      - id: check-added-large-files # 拦截超大文件提交(默认 500KB)
      #  args: ["--maxkb", "500"]      # 支持自定义修改
      - id: detect-private-key # 检测私钥/敏感信息泄露
  # ===== 以下为可选工具,按需启用 =====
  # - repo: https://github.com/gitleaks/gitleaks
  #   rev: v8.24.3
  #   hooks:
  #     - id: gitleaks                  # 密钥泄露检测
  # - repo: https://github.com/codespell-project/codespell
  #   rev: v2.4.1
  #   hooks:
  #     - id: codespell                 # 拼写检查
  # ===== Shell 必选工具:默认启用 =====
  - repo: https://github.com/scop/pre-commit-shfmt
    rev: v3.13.1-1
    hooks:
      - id: shfmt # Shell 脚本格式化(修复模式)
  - repo: https://github.com/shellcheck-py/shellcheck-py
    rev: v0.11.0.1
    hooks:
      - id: shellcheck # Shell 脚本静态分析

脚本集成测试、容器构建或端到端验证不适合放入 pre-commit,应在 PR 门禁、主干或夜间任务中单独执行。

4. 本地开发检查场景

本地开发以 pre-commit 为首选入口。Shfmt、ShellCheck、Gitleaks、Codespell 和官方基础 hook 均已由 .pre-commit-config.yaml 覆盖,本地默认检查只需要运行 pre-commit run --all-files,不需要再单独运行各工具原生命令。遇到误报时,先修正代码或配置,再使用 .shellcheckrc 或局部 # shellcheck disable=SCxxxx 做最小范围屏蔽。

4.1 本地检查流程

步骤 开发人员操作 依赖的工程配置 失败后怎么处理
安装工具 python -m pip install pre-commit,然后 pre-commit install .pre-commit-config.yaml 安装失败先确认 Python 版本和镜像源
自动修复 提交前自动触发 pre-commit hook .pre-commit-config.yaml.editorconfig 根据 hook 名称定位失败工具,先修复问题
提交前检查 pre-commit run --all-files 或提交时自动触发 .pre-commit-config.yaml、ignore 文件 格式问题由 Shfmt 自动修复,ShellCheck 问题按建议改代码
语言级检查 脚本集成测试等(如项目需要) 测试配置、CI workflow 本地无法复现时先同步依赖和 CI 环境版本

4.2 本地拦截与处理

拦截场景 常见原因 处理方式 是否可屏蔽
格式检查失败 未运行格式化、编辑器格式规则不一致 Shfmt 自动修复并提交 通常不屏蔽,生成文件用 ignore 排除
ShellCheck 失败 引用、数组、退出码、未定义变量等问题 按建议改代码;确实误报时用 # shellcheck disable=SCxxxx 单行屏蔽必须写明规则和原因
密钥检测失败 提交了 token、私钥、连接串或测试凭据 删除密钥、轮换凭据 只有确认假阳性时可用 allowlist
拼写检查失败 术语、品牌名、缩写未加入词典 修正拼写或加入 .codespellrc 业务术语可集中加入词典
基础语法失败 JSON/YAML/XML 不合法、脚本语法错误 修正语法或排除模板文件 模板文件可用 exclude 精确排除

5. PR 门禁检查场景

PR 门禁复用同一套 .pre-commit-config.yaml,确保本地和 CI 检查口径一致。PR 中建议对变更脚本增量检查;基础设施仓库建议主干再全量扫描所有脚本,避免长期遗漏 rarely touched 脚本。误报必须在代码评审里说明原因,优先通过集中配置或最小范围屏蔽处理。

5.1 PR 门禁使用的工程配置

配置 PR 中的用途 开发人员如何复现
.pre-commit-config.yaml 全仓轻量检查、密钥检测、拼写检查、Shell 格式和静态分析 本地运行 pre-commit run --all-files
.shellcheckrc ShellCheck 规则和排除配置 本地确认排除规则是否覆盖对应路径
CI workflow 固定运行环境、工具安装、检查顺序 对照 workflow 的 run 命令逐条执行

5.2 PR 拦截与修复

拦截场景 PR 中如何表现 开发人员处理方式 评审关注点
pre-commit 失败 CI 显示具体 hook 失败 本地运行同一 hook,提交修复结果 不接受直接跳过 hook 的提交
格式或 ShellCheck 失败 CI 输出文件路径和规则编号 Shfmt 自动修复;ShellCheck 按建议改代码 屏蔽必须限于最小范围
安全或密钥失败 Gitleaks 报告高风险问题 删除敏感内容、轮换凭据、解释假阳性 高风险问题必须修复或经安全确认
历史问题暴露 全量任务发现大量旧问题 新增问题阻断,历史问题进入治理任务 不能让新代码扩大历史问题范围

5.3 Shell PR 门禁命令

name: Shell Quality
on: [pull_request]
jobs:
  shell:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: python -m pip install pre-commit
      - run: pre-commit run --all-files

全量检查(主干合并后、发布前、夜间任务)建议运行 pre-commit run --all-files 覆盖全仓脚本;脚本集成测试和容器构建验证应在发布前或夜间任务中单独执行。误报处理遵循"先修正、再收敛规则、最后最小范围屏蔽"的顺序,具体屏蔽语法见 Shfmt 告警抑制ShellCheck 告警抑制

6. 落地步骤

  1. 先提交 .pre-commit-config.yaml.shellcheckrc.editorconfig 和 CI 工作流,不立即阻断历史问题。
  2. 对新项目直接开启严格规则;对存量项目先只检查变更文件或建立 baseline。
  3. 在 README 或贡献指南中写清本地命令、PR 门禁命令和误报屏蔽要求。
  4. 将 Shfmt 设置为自动修复(--write),ShellCheck 和安全扫描默认不自动改代码。
  5. 每次规则升级单独发 PR,避免与业务改动混在一起。
  6. 每季度清理一次 baseline、忽略列表和长期存在的屏蔽注释。