mcpField
S
shellcheck-configuration

shellcheck-configuration

github.com/ormus-solutions测试与质量12377 次安装4 周前更新
代码仓库

关于 shellcheck-configuration

这是一份配置 ShellCheck 并对 Shell 脚本进行静态分析的技能指南,面向维护 Shell 代码的开发者。内容介绍如何理解检查结果、调整规则,并将检查纳入开发与 CI 工作流。

主要功能

  1. 01项目与环境配置
  2. 02Shell 方言与规则选择
  3. 03警告代码及修复方法
  4. 04抑制指定检查结果
  5. 05集成预提交钩子与 CI
  6. 06用于自动化的输出格式

适用场景

  1. 01在 CI 中检查 Shell 脚本
  2. 02排查现有脚本问题
  3. 03按目标 Shell 配置检查规则
  4. 04处理误报与排除项

安装

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

$npx skills add https://github.com/ormus-solutions/libreuiux-claude-code --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