shellcheck-cicd-2025
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese🚨 CRITICAL GUIDELINES
⚠️ 关键指南
Windows File Path Requirements
Windows文件路径要求
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes () in file paths, NOT forward slashes ().
\/Examples:
- ❌ WRONG:
D:/repos/project/file.tsx - ✅ CORRECT:
D:\repos\project\file.tsx
This applies to:
- Edit tool file_path parameter
- Write tool file_path parameter
- All file operations on Windows systems
强制要求:在Windows系统中始终使用反斜杠(\)表示文件路径
在Windows系统中使用编辑或写入工具时,必须使用反斜杠()表示文件路径,而非正斜杠()。
\/示例:
- ❌ 错误:
D:/repos/project/file.tsx - ✅ 正确:
D:\repos\project\file.tsx
此要求适用于:
- 编辑工具的file_path参数
- 写入工具的file_path参数
- Windows系统上的所有文件操作
Documentation Guidelines
文档指南
NEVER create new documentation files unless explicitly requested by the user.
- Priority: Update existing README.md files rather than creating new documentation
- Repository cleanliness: Keep repository root clean - only README.md unless user requests otherwise
- Style: Documentation should be concise, direct, and professional - avoid AI-generated tone
- User preference: Only create additional .md files when user specifically asks for documentation
除非用户明确要求,否则绝不创建新的文档文件。
- 优先级:优先更新现有README.md文件,而非创建新文档
- 仓库整洁性:保持仓库根目录整洁 - 除非用户要求,否则仅保留README.md
- 风格:文档应简洁、直接、专业 - 避免AI生成的语气
- 用户偏好:仅在用户明确要求文档时才创建额外的.md文件
ShellCheck CI/CD Integration (2025)
ShellCheck CI/CD集成(2025版)
ShellCheck: Non-Negotiable in 2025
ShellCheck:2025年不可或缺的工具
ShellCheck is now considered mandatory in modern bash workflows (2025 best practices):
在2025年的现代Bash工作流中,ShellCheck已被视为强制使用的工具:
Latest Version: v0.11.0 (August 2025)
最新版本:v0.11.0(2025年8月)
What's New:
- Full Bash 5.3 support (and
${| cmd; })source -p - New warnings: SC2327/SC2328 (capture group issues)
- POSIX.1-2024 compliance: SC3013 removed (-ot/-nt/-ef now POSIX standard)
- Enhanced static analysis capabilities
- Improved performance and accuracy
新增特性:
- 全面支持Bash 5.3(包括和
${| cmd; }语法)source -p - 新增警告:SC2327/SC2328(捕获组问题)
- 符合POSIX.1-2024标准:移除SC3013规则(现已成为POSIX标准语法)
-ot/-nt/-ef - 增强的静态分析能力
- 提升的性能与准确性
Why Mandatory?
为何是强制要求?
- Catches subtle bugs before production
- Prevents common security vulnerabilities
- Enforces consistent code quality
- Required by most DevOps teams
- Standard in enterprise environments
- Supports latest POSIX.1-2024 standard
- 在上线前发现潜在的细微bug
- 预防常见的安全漏洞
- 保证代码质量的一致性
- 大多数DevOps团队的必备要求
- 企业环境中的标准配置
- 支持最新的POSIX.1-2024标准
Installation
安装方法
bash
undefinedbash
undefinedUbuntu/Debian
Ubuntu/Debian
apt-get install shellcheck
apt-get install shellcheck
macOS
macOS
brew install shellcheck
brew install shellcheck
Alpine (Docker)
Alpine (Docker)
apk add shellcheck
apk add shellcheck
Windows (WSL/Git Bash)
Windows (WSL/Git Bash)
choco install shellcheck
choco install shellcheck
Or download binary
或下载二进制文件
wget https://github.com/koalaman/shellcheck/releases/latest/download/shellcheck-stable.linux.x86_64.tar.xz
tar -xf shellcheck-stable.linux.x86_64.tar.xz
sudo cp shellcheck-stable/shellcheck /usr/local/bin/
undefinedwget https://github.com/koalaman/shellcheck/releases/latest/download/shellcheck-stable.linux.x86_64.tar.xz
tar -xf shellcheck-stable.linux.x86_64.tar.xz
sudo cp shellcheck-stable/shellcheck /usr/local/bin/
undefinedGitHub Actions Integration
GitHub Actions集成
Mandatory Pre-Merge Check
强制预合并检查
yaml
undefinedyaml
undefined.github/workflows/shellcheck.yml
.github/workflows/shellcheck.yml
name: ShellCheck
on:
pull_request:
paths:
- '**.sh'
- '**Dockerfile'
push:
branches: [main]
jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
with:
severity: warning
format: gcc # or: tty, json, checkstyle
scandir: './scripts'
# Fail on any issues
ignore_paths: 'node_modules'
# Block merge on failures
- name: Annotate PR
if: failure()
uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '⛔ ShellCheck validation failed. Fix issues before merging.'
})undefinedname: ShellCheck
on:
pull_request:
paths:
- '**.sh'
- '**Dockerfile'
push:
branches: [main]
jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 运行ShellCheck
uses: ludeeus/action-shellcheck@master
with:
severity: warning
format: gcc # 或:tty, json, checkstyle
scandir: './scripts'
# 存在任何问题则失败
ignore_paths: 'node_modules'
# 失败时阻止合并
- name: 为PR添加注释
if: failure()
uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '⛔ ShellCheck验证未通过。请修复问题后再合并。'
})undefinedAzure DevOps Integration
Azure DevOps集成
yaml
undefinedyaml
undefinedazure-pipelines.yml
azure-pipelines.yml
trigger:
- main
pr:
- main
stages:
- stage: Validate
jobs:
-
job: ShellCheck pool: vmImage: 'ubuntu-24.04'steps:
-
script: | sudo apt-get install -y shellcheck displayName: 'Install ShellCheck'
-
script: | find . -name "*.sh" -type f | xargs shellcheck --format=gcc --severity=warning displayName: 'Run ShellCheck' failOnStderr: true
-
task: PublishTestResults@2 condition: always() inputs: testResultsFormat: 'JUnit' testResultsFiles: '**/shellcheck-results.xml' failTaskOnFailedTests: true
-
-
undefinedtrigger:
- main
pr:
- main
stages:
- stage: 验证
jobs:
-
job: ShellCheck pool: vmImage: 'ubuntu-24.04'steps:
-
script: | sudo apt-get install -y shellcheck displayName: '安装ShellCheck'
-
script: | find . -name "*.sh" -type f | xargs shellcheck --format=gcc --severity=warning displayName: '运行ShellCheck' failOnStderr: true
-
task: PublishTestResults@2 condition: always() inputs: testResultsFormat: 'JUnit' testResultsFiles: '**/shellcheck-results.xml' failTaskOnFailedTests: true
-
-
undefinedGit Hooks (Pre-Commit)
Git钩子(预提交)
bash
undefinedbash
undefined.git/hooks/pre-commit
.git/hooks/pre-commit
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
Find all staged .sh files
查找所有已暂存的.sh文件
mapfile -t STAGED_SH < <(git diff --cached --name-only --diff-filter=ACMR | grep '.sh$' || true)
if [ ${#STAGED_SH[@]} -eq 0 ]; then
exit 0
fi
echo "Running ShellCheck on staged files..."
mapfile -t STAGED_SH < <(git diff --cached --name-only --diff-filter=ACMR | grep '.sh$' || true)
if [ ${#STAGED_SH[@]} -eq 0 ]; then
exit 0
fi
echo "正在对已暂存文件运行ShellCheck..."
Run ShellCheck
运行ShellCheck
shellcheck --format=gcc --severity=warning "${STAGED_SH[@]}"
if [ $? -ne 0 ]; then
echo "⛔ ShellCheck failed. Fix issues before committing."
exit 1
fi
echo "✅ ShellCheck passed"
exit 0
**Install Pre-Commit Hook:**
```bash
chmod +x .git/hooks/pre-commitshellcheck --format=gcc --severity=warning "${STAGED_SH[@]}"
if [ $? -ne 0 ]; then
echo "⛔ ShellCheck未通过。请修复问题后再提交。"
exit 1
fi
echo "✅ ShellCheck通过"
exit 0
**安装预提交钩子:**
```bash
chmod +x .git/hooks/pre-commitOr use pre-commit framework
或使用pre-commit框架
.pre-commit-config.yaml
.pre-commit-config.yaml
repos:
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.0
hooks:
- id: shellcheck args: ['--severity=warning']
repos:
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.0
hooks:
- id: shellcheck args: ['--severity=warning']
Install
安装
pip install pre-commit
pre-commit install
undefinedpip install pre-commit
pre-commit install
undefinedVS Code Integration
VS Code集成
json
// .vscode/settings.json
{
"shellcheck.enable": true,
"shellcheck.run": "onType",
"shellcheck.executablePath": "/usr/local/bin/shellcheck",
"shellcheck.exclude": ["SC1090", "SC1091"], // Optional excludes
"shellcheck.customArgs": [
"-x", // Follow source files
"--severity=warning"
]
}json
// .vscode/settings.json
{
"shellcheck.enable": true,
"shellcheck.run": "onType",
"shellcheck.executablePath": "/usr/local/bin/shellcheck",
"shellcheck.exclude": ["SC1090", "SC1091"], // 可选排除的规则
"shellcheck.customArgs": [
"-x", // 跟随源文件
"--severity=warning"
]
}Docker Build Integration
Docker构建集成
dockerfile
undefineddockerfile
undefinedDockerfile with ShellCheck validation
包含ShellCheck验证的Dockerfile
FROM alpine:3.19 AS builder
FROM alpine:3.19 AS builder
Install ShellCheck
安装ShellCheck
RUN apk add --no-cache shellcheck bash
RUN apk add --no-cache shellcheck bash
Copy scripts
复制脚本
COPY scripts/ /scripts/
COPY scripts/ /scripts/
Validate all scripts before continuing
在继续构建前验证所有脚本
RUN find /scripts -name "*.sh" -type f -exec shellcheck --severity=warning {} +
RUN find /scripts -name "*.sh" -type f -exec shellcheck --severity=warning {} +
Final stage
最终阶段
FROM alpine:3.19
COPY --from=builder /scripts/ /scripts/
RUN chmod +x /scripts/*.sh
ENTRYPOINT ["/scripts/entrypoint.sh"]
undefinedFROM alpine:3.19
COPY --from=builder /scripts/ /scripts/
RUN chmod +x /scripts/*.sh
ENTRYPOINT ["/scripts/entrypoint.sh"]
undefinedCommon ShellCheck Rules (2025)
常用ShellCheck规则(2025版)
New in v0.11.0: SC2327/SC2328 - Capture Groups
v0.11.0新增:SC2327/SC2328 - 捕获组问题
bash
undefinedbash
undefined❌ Bad - Capture groups may not work as expected
❌ 错误示例 - 捕获组可能无法按预期工作
if [[ "$string" =~ ([0-9]+).([0-9]+) ]]; then
echo "$1" # Wrong: $1 is script arg, not capture group
fi
if [[ "$string" =~ ([0-9]+).([0-9]+) ]]; then
echo "$1" # 错误:$1是脚本参数,而非捕获组
fi
✅ Good - Use BASH_REMATCH array
✅ 正确示例 - 使用BASH_REMATCH数组
if [[ "$string" =~ ([0-9]+).([0-9]+) ]]; then
echo "${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
fi
undefinedif [[ "$string" =~ ([0-9]+).([0-9]+) ]]; then
echo "${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
fi
undefinedSC2294: eval Negates Array Benefits (New)
SC2294:eval会抵消数组的安全性(新增规则)
bash
undefinedbash
undefined❌ Bad - eval defeats array safety
❌ 错误示例 - eval会破坏数组的安全性
eval "command ${array[@]}"
eval "command ${array[@]}"
✅ Good - Direct array usage
✅ 正确示例 - 直接使用数组
command "${array[@]}"
undefinedcommand "${array[@]}"
undefinedSC2295: Quote Expansions Inside ${}
SC2295:在${}内为扩展内容添加引号
bash
undefinedbash
undefined❌ Bad
❌ 错误示例
echo "${var-$default}" # $default not quoted
echo "${var-$default}" # $default未添加引号
✅ Good
✅ 正确示例
echo "${var-"$default"}"
undefinedecho "${var-"$default"}"
undefinedSC2086: Quote Variables
SC2086:为变量添加引号
bash
undefinedbash
undefined❌ Bad
❌ 错误示例
file=$1
cat $file # Fails if filename has spaces
file=$1
cat $file # 如果文件名包含空格会失败
✅ Good
✅ 正确示例
file=$1
cat "$file"
undefinedfile=$1
cat "$file"
undefinedSC2046: Quote Command Substitution
SC2046:为命令替换添加引号
bash
undefinedbash
undefined❌ Bad
❌ 错误示例
for file in $(find . -name "*.txt"); do
echo $file
done
for file in $(find . -name "*.txt"); do
echo $file
done
✅ Good
✅ 正确示例
find . -name "*.txt" -print0 | while IFS= read -r -d '' file; do
echo "$file"
done
undefinedfind . -name "*.txt" -print0 | while IFS= read -r -d '' file; do
echo "$file"
done
undefinedSC2155: Separate Declaration and Assignment
SC2155:变量声明与赋值分离
bash
undefinedbash
undefined❌ Bad
❌ 错误示例
local result=$(command) # Hides command exit code
local result=$(command) # 会隐藏命令的退出码
✅ Good
✅ 正确示例
local result
result=$(command)
undefinedlocal result
result=$(command)
undefinedSC2164: Use cd || exit
SC2164:使用cd || exit
bash
undefinedbash
undefined❌ Bad
❌ 错误示例
cd /some/directory
./script.sh # Runs in wrong dir if cd fails
cd /some/directory
./script.sh # 如果cd失败,会在错误的目录运行脚本
✅ Good
✅ 正确示例
cd /some/directory || exit 1
./script.sh
undefinedcd /some/directory || exit 1
./script.sh
undefinedGoogle Shell Style Guide (50-Line Limit)
Google Shell风格指南(50行限制)
2025 recommendation: Keep scripts under 50 lines:
bash
undefined2025年建议:脚本长度控制在50行以内
bash
undefined❌ Bad: 500-line monolithic script
❌ 错误示例:500行的单体脚本
#!/usr/bin/env bash
#!/usr/bin/env bash
... 500 lines of code ...
... 500行代码 ...
✅ Good: Modular scripts < 50 lines each
✅ 正确示例:模块化脚本,每个脚本不超过50行
lib/logging.sh (20 lines)
lib/logging.sh(20行)
log_info() { echo "[INFO] $"; }
log_error() { echo "[ERROR] $" >&2; }
log_info() { echo "[INFO] $"; }
log_error() { echo "[ERROR] $" >&2; }
lib/validation.sh (30 lines)
lib/validation.sh(30行)
validate_input() { ... }
check_dependencies() { ... }
validate_input() { ... }
check_dependencies() { ... }
main.sh (40 lines)
main.sh(40行)
source "$(dirname "$0")/lib/logging.sh"
source "$(dirname "$0")/lib/validation.sh"
main() {
validate_input "$@"
check_dependencies
... core logic ...
}
main "$@"
undefinedsource "$(dirname "$0")/lib/logging.sh"
source "$(dirname "$0")/lib/validation.sh"
main() {
validate_input "$@"
check_dependencies
... 核心逻辑 ...
}
main "$@"
undefinedEnforce in CI/CD
在CI/CD中强制执行
Fail Build on Issues
存在问题则构建失败
yaml
undefinedyaml
undefinedStrict enforcement
严格强制执行
- name: ShellCheck (Strict)
run: |
shellcheck --severity=warning scripts/*.sh
Exit code 1 fails the build
- run: |
shellcheck --severity=warning scripts/*.sh
退出码1会导致构建失败
Advisory only (warnings but don't fail)
仅作为建议(仅警告但不终止构建)
- name: ShellCheck (Advisory)
run: |
shellcheck --severity=warning scripts/*.sh || true
Logs warnings but doesn't fail
undefined- run: |
shellcheck --severity=warning scripts/*.sh || true
记录警告但不终止构建
undefinedGenerate Reports
生成报告
bash
undefinedbash
undefinedJSON format for parsing
用于解析的JSON格式
shellcheck --format=json scripts/*.sh > shellcheck-report.json
shellcheck --format=json scripts/*.sh > shellcheck-report.json
GitHub annotations format
GitHub注释格式
shellcheck --format=gcc scripts/*.sh
shellcheck --format=gcc scripts/*.sh
Human-readable
人类可读格式
shellcheck --format=tty scripts/*.sh
undefinedshellcheck --format=tty scripts/*.sh
undefinedModern Error Handling Trio (2025)
现代错误处理三件套(2025版)
Always use with ShellCheck validation:
bash
#!/usr/bin/env bash请始终与ShellCheck验证配合使用
bash
#!/usr/bin/env bashModern error handling (non-negotiable in 2025)
现代错误处理(2025年强制要求)
set -o errexit # Exit on command failure
set -o nounset # Exit on undefined variable
set -o pipefail # Exit on pipe failure
set -o errexit # 命令失败时退出
set -o nounset # 遇到未定义变量时退出
set -o pipefail # 管道失败时退出
ShellCheck approved
ShellCheck认可的写法
main() {
local config_file="${1:?Config file required}"
if [[ ! -f "$config_file" ]]; then
echo "Error: Config file not found: $config_file" >&2
return 1
fi
Safe command execution
local result
result=$(process_config "$config_file")
echo "$result"
}
main "$@"
undefinedmain() {
local config_file="${1:?必须提供配置文件}"
if [[ ! -f "$config_file" ]]; then
echo "错误:未找到配置文件:$config_file" >&2
return 1
fi
安全执行命令
local result
result=$(process_config "$config_file")
echo "$result"
}
main "$@"
undefinedBest Practices (2025)
最佳实践(2025版)
- Run ShellCheck in CI/CD (mandatory)
- Use pre-commit hooks to catch issues early
- Keep scripts under 50 lines (Google Style Guide)
- Use modern error handling trio (errexit, nounset, pipefail)
- Fix all warnings before merging
- Document any disabled rules with reasoning
- Integrate with IDE for real-time feedback
- 在CI/CD中运行ShellCheck(强制要求)
- 使用预提交钩子提前发现问题
- 将脚本长度控制在50行以内(Google风格指南)
- 使用现代错误处理三件套(errexit、nounset、pipefail)
- 合并前修复所有警告
- 对禁用的规则添加文档说明及原因
- 与IDE集成获取实时反馈