mcpField
S
shellcheck-configuration

shellcheck-configuration

github.com/ovachiever测试与质量5647 次安装48 周前更新
代码仓库

关于 shellcheck-configuration

为编写和维护 Shell 脚本的开发者提供 ShellCheck 静态分析配置与使用指南,涵盖规则调整、问题处理及 CI 集成。

主要功能

  1. 01配置目标 Shell 与规则
  2. 02解读常见警告代码
  3. 03处理误报与抑制警告
  4. 04集成 CI 和提交前检查
  5. 05选择分析输出格式

适用场景

  1. 01为项目设置 ShellCheck 规则
  2. 02在 CI 中检查 Shell 脚本
  3. 03排查脚本警告并修复
  4. 04按目标 Shell 检查可移植性

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ovachiever/droid-tings --skill shellcheck-configuration

安装后在 Claude Code 中输入/shellcheck-configuration确认已加载。

详细介绍

ShellCheck 配置与静态分析

全面介绍如何配置和使用 ShellCheck,通过静态代码分析提高 Shell 脚本质量、发现常见问题并贯彻最佳实践。

何时使用此技能

  • 为 CI/CD 流水线中的 Shell 脚本设置代码检查
  • 分析现有 Shell 脚本,查找问题
  • 了解 ShellCheck 错误代码和警告
  • 根据特定项目需求配置 ShellCheck
  • 将 ShellCheck 集成到开发工作流中
  • 忽略误报并配置规则集
  • 执行一致的代码质量标准
  • 迁移脚本以满足质量门槛

ShellCheck 基础知识

什么是 ShellCheck?

ShellCheck 是一种静态分析工具,可分析 Shell 脚本并检测有问题的模式。它支持:

  • 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(项目级)

在项目根目录中创建 .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

常见 ShellCheck 错误代码

SC1000-1099:解析器错误
# SC1004: Backslash continuation not followed by newline
echo hello\
world  # Error - needs line continuation

# SC1008: Invalid data for operator `=='
if [[ $var =  "value" ]]; then  # Space before ==
    true
fi
SC2000-2099:Shell 问题
# SC2009: Consider using pgrep or pidof instead of grep|grep
ps aux | grep -v grep | grep myprocess  # Use pgrep instead

# SC2012: Use `ls` only for viewing. Use `find` for reliable output
for file in $(ls -la)  # Better: use find or globbing

# SC2015: Avoid using && and || instead of if-then-else
[[ -f "$file" ]] && echo "found" || echo "not found"  # Less clear

# SC2016: Expressions don't expand in single quotes
echo '$VAR'  # Literal $VAR, not variable expansion

# SC2026: This word is non-standard. Set POSIXLY_CORRECT
# when using with scripts for other shells
SC2100-2199:引号问题
# SC2086: Double quote to prevent globbing and word splitting
for i in $list; do  # Should be: for i in $list or for i in "$list"
    echo "$i"
done

# SC2115: Literal tilde in path not expanded. Use $HOME instead
~/.bashrc  # In strings, use "$HOME/.bashrc"

# SC2181: Check exit code directly with `if`, not indirectly in a list
some_command
if [ $? -eq 0 ]; then  # Better: if some_command; then

# SC2206: Quote to prevent word splitting or set IFS
array=( $items )  # Should use: array=( $items )
SC3000-3999:POSIX 兼容性问题
# SC3010: In POSIX sh, use 'case' instead of 'cond && foo'
[[ $var == "value" ]] && do_something  # Not POSIX

# SC3043: In POSIX sh, use 'local' is undefined
function my_func() {
    local var=value  # Not POSIX in some shells
}

实用配置示例

最简配置(严格 POSIX)
#!/bin/bash
# Configure for maximum portability

shellcheck \
  --shell=sh \
  --external-sources \
  --check-sourced \
  script.sh
开发配置(放宽规则的 Bash)
#!/bin/bash
# Configure for Bash development

shellcheck \
  --shell=bash \
  --exclude=SC1091,SC2119 \
  --enable=all \
  script.sh
CI/CD 集成配置
#!/bin/bash
set -Eeuo pipefail

# Analyze all shell scripts and fail on issues
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 dialect to analyze against
shell=bash

# Enable optional checks
enable=avoid-nullary-conditions,require-variable-braces,check-unassigned-uppercase

# Disable specific warnings
# SC1091: Not following sourced files (many false positives)
disable=SC1091

# SC2119: Use function_name instead of function_name -- (arguments)
disable=SC2119

# External files to source for context
external-sources=true

集成模式

Pre-commit Hook 配置
#!/bin/bash
# .git/hooks/pre-commit

#!/bin/bash
set -e

# Find all shell scripts changed in this commit
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

处理 ShellCheck 违规项

忽略特定警告
#!/bin/bash

# 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 multiple warnings (format varies)
command_that_fails() {
    # shellcheck disable=SC2015
    [ -f "$1" ] && echo "found" || echo "not found"
}

# Disable specific check for source directive
# shellcheck source=./helper.sh
source helper.sh
常见违规项及修复方法
SC2086:使用双引号以防止单词拆分
# Problem
for i in $list; do done

# Solution
for i in $list; do done  # If $list is already quoted, or
for i in "${list[@]}"; do done  # If list is an array
SC2181:直接检查退出代码
# Problem
some_command
if [ $? -eq 0 ]; then
    echo "success"
fi

# Solution
if some_command; then
    echo "success"
fi
SC2015:使用 if-then 代替 && ||
# Problem
[ -f "$file" ] && echo "exists" || echo "not found"

# Solution - clearer intent
if [ -f "$file" ]; then
    echo "exists"
else
    echo "not found"
fi
SC2016:单引号中的表达式不会展开
# Problem
echo 'Variable value: $VAR'

# Solution
echo "Variable value: $VAR"
SC2009:使用 pgrep 代替 grep
# Problem
ps aux | grep -v grep | grep myprocess

# Solution
pgrep -f myprocess

性能优化

检查多个文件
#!/bin/bash

# Sequential checking
for script in *.sh; do
    shellcheck "$script"
done

# Parallel checking (faster)
find . -name "*.sh" -print0 | \
    xargs -0 -P 4 -n 1 shellcheck
缓存结果
#!/bin/bash

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

# Output:
# script.sh:1:3: warning: foo is referenced but not assigned. [SC2154]
GCC 格式(用于 CI/CD)
shellcheck --format=gcc script.sh

# Output:
# script.sh:1:3: warning: foo is referenced but not assigned.
JSON 格式(用于解析)
shellcheck --format=json script.sh

# Output:
# [{"file": "script.sh", "line": 1, "column": 3, "level": "warning", "code": 2154, "message": "..."}]
静默格式
shellcheck --format=quiet script.sh

# Returns non-zero if issues found, no output otherwise

最佳实践

  1. 在 CI/CD 中运行 ShellCheck - 在合并前发现问题
  2. 针对目标 Shell 进行配置 - 不要将 Bash 按 sh 分析
  3. 记录排除项 - 说明忽略违规项的原因
  4. 处理违规项 - 不要只是禁用警告
  5. 启用严格模式 - 使用 --enable=all 并谨慎排除
  6. 定期更新 - 保持 ShellCheck 为最新版本,以获取新的检查项
  7. 使用 pre-commit hooks - 在本地推送前发现问题
  8. 与编辑器集成 - 在开发过程中获取实时反馈

资源

评论

支持 Markdown