SuperAPI AI 工具集

shellcheck-configuration

编程与开发

查看项目

更新于 10-16 07:46

技能介绍

用途

ShellCheck 是一个静态分析工具,用于分析 Shell 脚本并检测有问题的模式。本技能提供配置和使用 ShellCheck 的全面指导,帮助改进 Shell 脚本质量、捕获常见陷阱,并通过静态代码分析强制执行最佳实践。

适用场景包括:

  • 在 CI/CD 流水线中为 Shell 脚本搭建 lint 检查
  • 分析现有 Shell 脚本中的问题
  • 理解 ShellCheck 错误码和警告
  • 针对特定项目需求配置 ShellCheck
  • 将 ShellCheck 集成到开发工作流中
  • 抑制误报并配置规则集
  • 强制执行一致的代码质量标准
  • 迁移脚本以满足质量门禁

主要能力

ShellCheck 支持 Bash、sh、dash、ksh 及其他 POSIX shell,提供超过 100 种警告和错误,可配置目标 shell 和标志,并能与编辑器和 CI/CD 系统集成。

安装

# macOS with Homebrew
brew install shellcheck

# Ubuntu/Debian
apt-get install shellcheck

# From source
git clone https://github.com/koalaman/shellcheck.git
cd shellcheck
make build
make install

# Verify installation
shellcheck --version

配置文件

项目级 .shellcheckrc(放在项目根目录):

# Specify target shell
shell=bash

# Enable optional checks
enable=avoid-nullary-conditions
enable=require-variable-braces

# Disable specific warnings
disable=SC1091
disable=SC2086

环境变量:

# Set default shell target
export SHELLCHECK_SHELL=bash

# Enable strict mode
export SHELLCHECK_STRICT=true

# Specify configuration file location
export SHELLCHECK_CONFIG=~/.shellcheckrc

常见错误码

  • SC1000-1099:解析器错误,如 SC1004(反斜杠续行后未换行)、SC1008(== 运算符数据无效)。
  • SC2000-2099:Shell 问题,如 SC2009(建议用 pgrep 或 pidof 替代 grep|grep)、SC2012(ls 仅用于查看,可靠输出用 find)、SC2015(避免用 && 和 || 替代 if-then-else)、SC2016(单引号内表达式不展开)。
  • SC2100-2199:引用问题,如 SC2086(双引号防止通配和分词)、SC2115(路径中的字面量波浪号不展开,改用 $HOME)、SC2181(直接用 if 检查退出码)、SC2206(引用防止分词或设置 IFS)。
  • SC3000-3999:POSIX 合规问题,如 SC3010(POSIX sh 中用 case 替代 cond && foo)、SC3043(POSIX sh 中 local 未定义)。

使用方式

配置示例

最小配置(严格 POSIX):

shellcheck \
  --shell=sh \
  --external-sources \
  --check-sourced \
  script.sh

开发配置(Bash 宽松规则):

shellcheck \
  --shell=bash \
  --exclude=SC1091,SC2119 \
  --enable=all \
  script.sh

CI/CD 集成配置:

set -Eeuo pipefail

find . -type f -name "*.sh" | while read -r script; do
    echo "Checking: $script"
    shellcheck \
        --shell=bash \
        --format=gcc \
        --exclude=SC1091 \
        "$script" || exit 1
done

项目 .shellcheckrc:

shell=bash
enable=avoid-nullary-conditions,require-variable-braces,check-unassigned-uppercase
disable=SC1091
disable=SC2119
external-sources=true

集成模式

Pre-commit 钩子(.git/hooks/pre-commit):

set -e

git diff --cached --name-only | grep '\.sh$' | while read -r script; do
    echo "Linting: $script"
    if ! shellcheck "$script"; then
        echo "ShellCheck failed on $script"
        exit 1
    fi
done

GitHub Actions 工作流:

name: ShellCheck
on: [push, pull_request]
jobs:
  shellcheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run ShellCheck
        run: |
          sudo apt-get install shellcheck
          find . -type f -name "*.sh" -exec shellcheck {} \;

GitLab CI 流水线:

shellcheck:
  stage: lint
  image: koalaman/shellcheck-alpine
  script:
    - find . -type f -name "*.sh" -exec shellcheck {} \;
  allow_failure: false

处理违规

抑制特定警告:

# Disable warning for entire line
# shellcheck disable=SC2086
for file in $(ls -la); do
    echo "$file"
done

# Disable for entire script
# shellcheck disable=SC1091,SC2119

# Disable specific check for source directive
# shellcheck source=./helper.sh
source helper.sh

常见违规修复:

  • SC2086:for i in $list; do done 改为 for i in "${list[@]}"; do done(若为数组)。
  • SC2181:some_command; if [ $? -eq 0 ]; then 改为 if some_command; then。
  • SC2015:[ -f "$file" ] && echo "exists" || echo "not found" 改为 if-then-else。
  • SC2016:echo 'Variable value: $VAR' 改为 echo "Variable value: $VAR"。
  • SC2009:ps aux | grep -v grep | grep myprocess 改为 pgrep -f myprocess。

性能优化

并行检查:

find . -name "*.sh" -print0 | \
    xargs -0 -P 4 -n 1 shellcheck

缓存结果:

CACHE_DIR=".shellcheck_cache"
mkdir -p "$CACHE_DIR"

check_script() {
    local script="$1"
    local hash
    local cache_file

    hash=$(sha256sum "$script" | cut -d' ' -f1)
    cache_file="$CACHE_DIR/$hash"

    if [[ ! -f "$cache_file" ]]; then
        if shellcheck "$script" > "$cache_file" 2>&1; then
            touch "$cache_file.ok"
        else
            return 1
        fi
    fi

    [[ -f "$cache_file.ok" ]]
}

find . -name "*.sh" | while read -r script; do
    check_script "$script" || exit 1
done

输出格式

  • 默认格式:shellcheck script.sh,输出如 script.sh:1:3: warning: foo is referenced but not assigned. [SC2154]。
  • GCC 格式(用于 CI/CD):shellcheck --format=gcc script.sh。
  • JSON 格式(用于解析):shellcheck --format=json script.sh。
  • 安静格式:shellcheck --format=quiet script.sh,发现问题返回非零,否则无输出。

适用场景

  • 在 CI/CD 中运行 ShellCheck,在合并前捕获问题
  • 针对目标 shell 进行配置,避免将 bash 当作 sh 分析
  • 记录排除项,解释为何抑制违规
  • 解决违规而非仅禁用警告
  • 启用严格模式,使用 --enable=all 并谨慎排除
  • 定期更新 ShellCheck 以获取新检查
  • 使用 pre-commit 钩子在推送前本地捕获问题
  • 与编辑器集成,在开发过程中获得实时反馈

限制

资料未提供 ShellCheck 的收费、价格、平台限制或具体效果数据。部分错误码示例中的修复建议在原文中未完整给出,实际使用时请参考 ShellCheck 官方 Wiki 和错误码参考。

资源

  • ShellCheck GitHub:https://github.com/koalaman/shellcheck
  • ShellCheck Wiki:https://www.shellcheck.net/wiki/
  • 错误码参考:https://www.shellcheck.net/