shellcheck-configuration
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseShellCheck Configuration and Static Analysis
ShellCheck 配置与静态分析
Comprehensive guidance for configuring and using ShellCheck to improve shell script quality, catch common pitfalls, and enforce best practices through static code analysis.
本文提供配置和使用ShellCheck的全面指南,通过静态代码分析提升Shell脚本质量、排查常见问题并践行最佳实践。
When to Use This Skill
适用场景
- Setting up linting for shell scripts in CI/CD pipelines
- Analyzing existing shell scripts for issues
- Understanding ShellCheck error codes and warnings
- Configuring ShellCheck for specific project requirements
- Integrating ShellCheck into development workflows
- Suppressing false positives and configuring rule sets
- Enforcing consistent code quality standards
- Migrating scripts to meet quality gates
- 在CI/CD流水线中为Shell脚本搭建代码检查机制
- 分析现有Shell脚本中的问题
- 理解ShellCheck错误码与警告信息
- 根据项目需求配置ShellCheck
- 将ShellCheck集成到开发工作流中
- 抑制误报并配置规则集
- 推行一致的代码质量标准
- 迁移脚本以满足质量要求
ShellCheck Fundamentals
ShellCheck 基础
What is ShellCheck?
什么是ShellCheck?
ShellCheck is a static analysis tool that analyzes shell scripts and detects problematic patterns. It supports:
- Bash, sh, dash, ksh, and other POSIX shells
- Over 100 different warnings and errors
- Configuration for target shell and flags
- Integration with editors and CI/CD systems
ShellCheck是一款静态分析工具,用于分析Shell脚本并检测有问题的代码模式。它支持:
- Bash、sh、dash、ksh及其他POSIX兼容Shell
- 超过100种不同的警告与错误类型
- 针对目标Shell和参数的配置
- 与编辑器及CI/CD系统的集成
Installation
安装方法
bash
undefinedbash
undefinedmacOS with Homebrew
macOS 系统使用 Homebrew
brew install shellcheck
brew install shellcheck
Ubuntu/Debian
Ubuntu/Debian 系统
apt-get install shellcheck
apt-get install shellcheck
From source
从源码编译安装
git clone https://github.com/koalaman/shellcheck.git
cd shellcheck
make build
make install
git clone https://github.com/koalaman/shellcheck.git
cd shellcheck
make build
make install
Verify installation
验证安装
shellcheck --version
undefinedshellcheck --version
undefinedConfiguration Files
配置文件
.shellcheckrc (Project Level)
.shellcheckrc(项目级配置)
Create in your project root:
.shellcheckrcundefined在项目根目录创建 文件:
.shellcheckrcundefinedSpecify target shell
指定目标Shell
shell=bash
shell=bash
Enable optional checks
启用可选检查规则
enable=avoid-nullary-conditions
enable=require-variable-braces
enable=avoid-nullary-conditions
enable=require-variable-braces
Disable specific warnings
禁用特定警告
disable=SC1091
disable=SC2086
undefineddisable=SC1091
disable=SC2086
undefinedEnvironment Variables
环境变量配置
bash
undefinedbash
undefinedSet default shell target
设置默认目标Shell
export SHELLCHECK_SHELL=bash
export SHELLCHECK_SHELL=bash
Enable strict mode
启用严格模式
export SHELLCHECK_STRICT=true
export SHELLCHECK_STRICT=true
Specify configuration file location
指定配置文件位置
export SHELLCHECK_CONFIG=~/.shellcheckrc
undefinedexport SHELLCHECK_CONFIG=~/.shellcheckrc
undefinedCommon ShellCheck Error Codes
常见ShellCheck错误码
SC1000-1099: Parser Errors
SC1000-1099:解析器错误
bash
undefinedbash
undefinedSC1004: Backslash continuation not followed by newline
SC1004:反斜杠续行后未换行
echo hello
world # Error - needs line continuation
world # Error - needs line continuation
echo hello
world # 错误 - 需要正确的换行续行
world # 错误 - 需要正确的换行续行
SC1008: Invalid data for operator `=='
SC1008:运算符 ==
使用无效数据
==if [[ $var = "value" ]]; then # Space before ==
true
fi
undefinedif [[ $var = "value" ]]; then # == 前存在多余空格
true
fi
undefinedSC2000-2099: Shell Issues
SC2000-2099:Shell相关问题
bash
undefinedbash
undefinedSC2009: Consider using pgrep or pidof instead of grep|grep
SC2009:建议使用 pgrep 或 pidof 替代 grep|grep
ps aux | grep -v grep | grep myprocess # Use pgrep instead
ps aux | grep -v grep | grep myprocess # 建议改用 pgrep
SC2012: Use ls
only for viewing. Use find
for reliable output
lsfindSC2012:仅在查看内容时使用 ls
,如需可靠输出请使用 find
lsfindfor file in $(ls -la) # Better: use find or globbing
for file in $(ls -la) # 更佳方案:使用 find 或通配符
SC2015: Avoid using && and || instead of if-then-else
SC2015:避免用 && 和 || 替代 if-then-else 结构
[[ -f "$file" ]] && echo "found" || echo "not found" # Less clear
[[ -f "$file" ]] && echo "found" || echo "not found" # 可读性较差
SC2016: Expressions don't expand in single quotes
SC2016:单引号中的表达式不会展开
echo '$VAR' # Literal $VAR, not variable expansion
echo '$VAR' # 输出字面量 $VAR,而非变量值
SC2026: This word is non-standard. Set POSIXLY_CORRECT
SC2026:该关键字不符合标准。若为其他Shell编写脚本,请设置 POSIXLY_CORRECT
when using with scripts for other shells
—
undefinedundefinedSC2100-2199: Quoting Issues
SC2100-2199:引号相关问题
bash
undefinedbash
undefinedSC2086: Double quote to prevent globbing and word splitting
SC2086:请使用双引号避免通配符与单词拆分
for i in $list; do # Should be: for i in $list or for i in "$list"
echo "$i"
done
for i in $list; do # 正确写法:for i in "$list" 或 for i in "${list[@]}"
echo "$i"
done
SC2115: Literal tilde in path not expanded. Use $HOME instead
SC2115:路径中的字面波浪号不会展开,请改用 $HOME
~/.bashrc # In strings, use "$HOME/.bashrc"
~/.bashrc # 在字符串中请使用 "$HOME/.bashrc"
SC2181: Check exit code directly with if
, not indirectly in a list
ifSC2181:请直接用 if
检查退出码,而非间接通过列表判断
ifsome_command
if [ $? -eq 0 ]; then # Better: if some_command; then
some_command
if [ $? -eq 0 ]; then # 更佳方案:if some_command; then
SC2206: Quote to prevent word splitting or set IFS
SC2206:请添加引号避免单词拆分,或设置 IFS
array=( $items ) # Should use: array=( $items )
undefinedarray=( $items ) # 正确写法:array=( "$items" )
undefinedSC3000-3999: POSIX Compliance Issues
SC3000-3999:POSIX兼容性问题
bash
undefinedbash
undefinedSC3010: In POSIX sh, use 'case' instead of 'cond && foo'
SC3010:在POSIX sh中,请用 'case' 替代 'cond && foo' 结构
[[ $var == "value" ]] && do_something # Not POSIX
[[ $var == "value" ]] && do_something # 不符合POSIX标准
SC3043: In POSIX sh, use 'local' is undefined
SC3043:在POSIX sh中,'local' 未定义
function my_func() {
local var=value # Not POSIX in some shells
}
undefinedfunction my_func() {
local var=value # 在部分Shell中不符合POSIX标准
}
undefinedPractical Configuration Examples
实用配置示例
Minimal Configuration (Strict POSIX)
最小配置(严格POSIX兼容)
bash
#!/bin/bashbash
#!/bin/bashConfigure for maximum portability
配置以实现最大可移植性
shellcheck
--shell=sh
--external-sources
--check-sourced
script.sh
--shell=sh
--external-sources
--check-sourced
script.sh
undefinedshellcheck
--shell=sh
--external-sources
--check-sourced
script.sh
--shell=sh
--external-sources
--check-sourced
script.sh
undefinedDevelopment Configuration (Bash with Relaxed Rules)
开发配置(Bash宽松规则)
bash
#!/bin/bashbash
#!/bin/bashConfigure for Bash development
为Bash开发场景配置
shellcheck
--shell=bash
--exclude=SC1091,SC2119
--enable=all
script.sh
--shell=bash
--exclude=SC1091,SC2119
--enable=all
script.sh
undefinedshellcheck
--shell=bash
--exclude=SC1091,SC2119
--enable=all
script.sh
--shell=bash
--exclude=SC1091,SC2119
--enable=all
script.sh
undefinedCI/CD Integration Configuration
CI/CD集成配置
bash
#!/bin/bash
set -Eeuo pipefailbash
#!/bin/bash
set -Eeuo pipefailAnalyze all shell scripts and fail on issues
分析所有Shell脚本,发现问题则终止流程
find . -type f -name "*.sh" | while read -r script; do
echo "Checking: $script"
shellcheck
--shell=bash
--format=gcc
--exclude=SC1091
"$script" || exit 1 done
--shell=bash
--format=gcc
--exclude=SC1091
"$script" || exit 1 done
undefinedfind . -type f -name "*.sh" | while read -r script; do
echo "检查中: $script"
shellcheck
--shell=bash
--format=gcc
--exclude=SC1091
"$script" || exit 1 done
--shell=bash
--format=gcc
--exclude=SC1091
"$script" || exit 1 done
undefined.shellcheckrc for Project
项目级 .shellcheckrc 配置
undefinedundefinedShell dialect to analyze against
指定要分析的Shell方言
shell=bash
shell=bash
Enable optional checks
启用可选检查规则
enable=avoid-nullary-conditions,require-variable-braces,check-unassigned-uppercase
enable=avoid-nullary-conditions,require-variable-braces,check-unassigned-uppercase
Disable specific warnings
禁用特定警告
SC1091: Not following sourced files (many false positives)
SC1091:不追踪被引入的文件(存在大量误报)
disable=SC1091
disable=SC1091
SC2119: Use function_name instead of function_name -- (arguments)
SC2119:请使用 function_name 而非 function_name -- (参数)
disable=SC2119
disable=SC2119
External files to source for context
允许引入外部文件以获取上下文
external-sources=true
undefinedexternal-sources=true
undefinedIntegration Patterns
集成模式
Pre-commit Hook Configuration
预提交钩子配置
bash
#!/bin/bashbash
#!/bin/bash.git/hooks/pre-commit
.git/hooks/pre-commit
#!/bin/bash
set -e
#!/bin/bash
set -e
Find all shell scripts changed in this commit
找出本次提交中修改的所有Shell脚本
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
fidone
undefinedgit diff --cached --name-only | grep '.sh$' | while read -r script; do
echo "代码检查: $script"
if ! shellcheck "$script"; then
echo "ShellCheck 在 $script 中发现问题"
exit 1
fidone
undefinedGitHub Actions Workflow
GitHub Actions 工作流配置
yaml
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 {} \;yaml
name: ShellCheck
on: [push, pull_request]
jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 运行 ShellCheck
run: |
sudo apt-get install shellcheck
find . -type f -name "*.sh" -exec shellcheck {} \;GitLab CI Pipeline
GitLab CI 流水线配置
yaml
shellcheck:
stage: lint
image: koalaman/shellcheck-alpine
script:
- find . -type f -name "*.sh" -exec shellcheck {} \;
allow_failure: falseyaml
shellcheck:
stage: lint
image: koalaman/shellcheck-alpine
script:
- find . -type f -name "*.sh" -exec shellcheck {} \;
allow_failure: falseHandling ShellCheck Violations
处理ShellCheck违规问题
Suppressing Specific Warnings
抑制特定警告
bash
#!/bin/bashbash
#!/bin/bashDisable warning for entire line
禁用整行的警告
shellcheck disable=SC2086
shellcheck disable=SC2086
for file in $(ls -la); do
echo "$file"
done
for file in $(ls -la); do
echo "$file"
done
Disable for entire script
禁用整个脚本的警告
shellcheck disable=SC1091,SC2119
shellcheck disable=SC1091,SC2119
Disable multiple warnings (format varies)
禁用多个警告(格式略有不同)
command_that_fails() {
# shellcheck disable=SC2015
[ -f "$1" ] && echo "found" || echo "not found"
}
command_that_fails() {
# shellcheck disable=SC2015
[ -f "$1" ] && echo "found" || echo "not found"
}
Disable specific check for source directive
为source指令禁用特定检查
shellcheck source=./helper.sh
shellcheck source=./helper.sh
source helper.sh
undefinedsource helper.sh
undefinedCommon Violations and Fixes
常见违规问题与修复方案
SC2086: Double quote to prevent word splitting
SC2086:使用双引号避免单词拆分
bash
undefinedbash
undefinedProblem
问题代码
for i in $list; do done
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
undefinedfor i in "$list"; do done # 若 $list 已被引号包裹,或
for i in "${list[@]}"; do done # 若 list 是数组
undefinedSC2181: Check exit code directly
SC2181:直接检查退出码
bash
undefinedbash
undefinedProblem
问题代码
some_command
if [ $? -eq 0 ]; then
echo "success"
fi
some_command
if [ $? -eq 0 ]; then
echo "成功"
fi
Solution
修复方案
if some_command; then
echo "success"
fi
undefinedif some_command; then
echo "成功"
fi
undefinedSC2015: Use if-then instead of && ||
SC2015:使用if-then替代 && || 结构
bash
undefinedbash
undefinedProblem
问题代码
[ -f "$file" ] && echo "exists" || echo "not found"
[ -f "$file" ] && echo "存在" || echo "不存在"
Solution - clearer intent
修复方案 - 意图更清晰
if [ -f "$file" ]; then
echo "exists"
else
echo "not found"
fi
undefinedif [ -f "$file" ]; then
echo "存在"
else
echo "不存在"
fi
undefinedSC2016: Expressions don't expand in single quotes
SC2016:单引号中的表达式不会展开
bash
undefinedbash
undefinedProblem
问题代码
echo 'Variable value: $VAR'
echo '变量值: $VAR'
Solution
修复方案
echo "Variable value: $VAR"
undefinedecho "变量值: $VAR"
undefinedSC2009: Use pgrep instead of grep
SC2009:使用pgrep替代grep
bash
undefinedbash
undefinedProblem
问题代码
ps aux | grep -v grep | grep myprocess
ps aux | grep -v grep | grep myprocess
Solution
修复方案
pgrep -f myprocess
undefinedpgrep -f myprocess
undefinedPerformance Optimization
性能优化
Checking Multiple Files
检查多个文件
bash
#!/bin/bashbash
#!/bin/bashSequential checking
串行检查
for script in *.sh; do
shellcheck "$script"
done
for script in *.sh; do
shellcheck "$script"
done
Parallel checking (faster)
并行检查(速度更快)
find . -name "*.sh" -print0 |
xargs -0 -P 4 -n 1 shellcheck
xargs -0 -P 4 -n 1 shellcheck
undefinedfind . -name "*.sh" -print0 |
xargs -0 -P 4 -n 1 shellcheck
xargs -0 -P 4 -n 1 shellcheck
undefinedCaching Results
缓存检查结果
bash
#!/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
donebash
#!/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
doneOutput Formats
输出格式
Default Format
默认格式
bash
shellcheck script.shbash
shellcheck script.shOutput:
输出示例:
script.sh:1:3: warning: foo is referenced but not assigned. [SC2154]
script.sh:1:3: warning: foo is referenced but not assigned. [SC2154]
undefinedundefinedGCC Format (for CI/CD)
GCC格式(适用于CI/CD)
bash
shellcheck --format=gcc script.shbash
shellcheck --format=gcc script.shOutput:
输出示例:
script.sh:1:3: warning: foo is referenced but not assigned.
script.sh:1:3: warning: foo is referenced but not assigned.
undefinedundefinedJSON Format (for parsing)
JSON格式(适用于解析)
bash
shellcheck --format=json script.shbash
shellcheck --format=json script.shOutput:
输出示例:
[{"file": "script.sh", "line": 1, "column": 3, "level": "warning", "code": 2154, "message": "..."}]
[{"file": "script.sh", "line": 1, "column": 3, "level": "warning", "code": 2154, "message": "..."}]
undefinedundefinedQuiet Format
静默格式
bash
shellcheck --format=quiet script.shbash
shellcheck --format=quiet script.shReturns non-zero if issues found, no output otherwise
发现问题时返回非零值,无其他输出
undefinedundefinedBest Practices
最佳实践
- Run ShellCheck in CI/CD - Catch issues before merging
- Configure for your target shell - Don't analyze bash as sh
- Document exclusions - Explain why violations are suppressed
- Address violations - Don't just disable warnings
- Enable strict mode - Use with careful exclusions
--enable=all - Update regularly - Keep ShellCheck current for new checks
- Use pre-commit hooks - Catch issues locally before pushing
- Integrate with editors - Get real-time feedback during development
- 在CI/CD中运行ShellCheck - 在代码合并前发现问题
- 针对目标Shell配置 - 不要将Bash脚本按sh分析
- 记录规则排除原因 - 说明为何要抑制某些违规警告
- 解决违规问题 - 不要仅禁用警告
- 启用严格模式 - 谨慎排除规则的同时使用
--enable=all - 定期更新ShellCheck - 保持工具版本以获取新的检查规则
- 使用预提交钩子 - 在本地推送代码前发现问题
- 与编辑器集成 - 在开发过程中获取实时反馈
Resources
参考资源
- ShellCheck GitHub: https://github.com/koalaman/shellcheck
- ShellCheck Wiki: https://www.shellcheck.net/wiki/
- Error Code Reference: https://www.shellcheck.net/
- ShellCheck GitHub: https://github.com/koalaman/shellcheck
- ShellCheck Wiki: https://www.shellcheck.net/wiki/
- 错误码参考: https://www.shellcheck.net/