| name | shellcheck-configuration |
| description | Master ShellCheck static analysis configuration and usage for shell script quality. Use when setting up linting infrastructure, fixing code issues, or ensuring script portability. |
ShellCheck Configuration and Static Analysis
Comprehensive guidance for configuring and using ShellCheck to improve shell script quality, catch common pitfalls, and enforce best practices through static code analysis.
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
ShellCheck Fundamentals
What is 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
Installation
brew install shellcheck
apt-get install shellcheck
git clone https://github.com/koalaman/shellcheck.git
cd shellcheck
make build
make install
shellcheck --version
Configuration Files
.shellcheckrc (Project Level)
Create .shellcheckrc in your project root:
# Specify target shell
shell=bash
# Enable optional checks
enable=avoid-nullary-conditions
enable=require-variable-braces
# Disable specific warnings
disable=SC1091
disable=SC2086
Environment Variables
export SHELLCHECK_SHELL=bash
export SHELLCHECK_STRICT=true
export SHELLCHECK_CONFIG=~/.shellcheckrc
Common ShellCheck Error Codes
SC1000-1099: Parser Errors
echo hello\
world
if [[ $var = "value" ]]; then
true
fi
SC2000-2099: Shell Issues
ps aux | grep -v grep | grep myprocess
for file in $(ls -la)
[[ -f "$file" ]] && echo "found" || echo "not found"
echo '$VAR'
SC2100-2199: Quoting Issues
for i in $list; do
echo "$i"
done
~/.bashrc
some_command
if [ $? -eq 0 ]; then
array=( $items )
SC3000-3999: POSIX Compliance Issues
[[ $var == "value" ]] && do_something
function my_func() {
local var=value
}
Practical Configuration Examples
Minimal Configuration (Strict POSIX)
#!/bin/bash
shellcheck \
--shell=sh \
--external-sources \
--check-sourced \
script.sh
Development Configuration (Bash with Relaxed Rules)
#!/bin/bash
shellcheck \
--shell=bash \
--exclude=SC1091,SC2119 \
--enable=all \
script.sh
CI/CD Integration Configuration
#!/bin/bash
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 for Project
# 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
Integration Patterns
Pre-commit Hook Configuration
#!/bin/bash
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 Workflow
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 Pipeline
shellcheck:
stage: lint
image: koalaman/shellcheck-alpine
script:
- find . -type f -name "*.sh" -exec shellcheck {} \;
allow_failure: false
Handling ShellCheck Violations
Suppressing Specific Warnings
#!/bin/bash
for file in $(ls -la); do
echo "$file"
done
command_that_fails() {
[ -f "$1" ] && echo "found" || echo "not found"
}
source helper.sh
Common Violations and Fixes
SC2086: Double quote to prevent word splitting
for i in $list; do done
for i in $list; do done
for i in "${list[@]}"; do done
SC2181: Check exit code directly
some_command
if [ $? -eq 0 ]; then
echo "success"
fi
if some_command; then
echo "success"
fi
SC2015: Use if-then instead of && ||
[ -f "$file" ] && echo "exists" || echo "not found"
if [ -f "$file" ]; then
echo "exists"
else
echo "not found"
fi
SC2016: Expressions don't expand in single quotes
echo 'Variable value: $VAR'
echo "Variable value: $VAR"
SC2009: Use pgrep instead of grep
ps aux | grep -v grep | grep myprocess
pgrep -f myprocess
Performance Optimization
Checking Multiple Files
#!/bin/bash
for script in *.sh; do
shellcheck "$script"
done
find . -name "*.sh" -print0 | \
xargs -0 -P 4 -n 1 shellcheck
Caching Results
#!/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
Output Formats
Default Format
shellcheck script.sh
GCC Format (for CI/CD)
shellcheck --format=gcc script.sh
JSON Format (for parsing)
shellcheck --format=json script.sh
Quiet Format
shellcheck --format=quiet script.sh
Best 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
--enable=all with careful exclusions
- 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