sh/Bash脚本静态分析和lint工具:ShellCheck
jopen
10年前
sh/Bash脚本静态分析和lint工具:ShellCheck。它不仅主要关注shell脚本典型初中级语法错误和shell输出的神秘的错误信息或者奇怪行为的缺陷,也能报告一些高级导致后来故障的高级问题。
What does ShellCheck check?
Here is an incomplete list of things ShellCheck warns about and suggests improvements to:
Unquoted globs for find/grep
find . -name *.ogg</div>
Constant test expressions
[[ n != 0 ]]</div>
Assigning arrays to strings
args="$@"</div>
Redirecting into source file
sed -e 's/foo/bar/g' file > file</div>
Existence checks of globs
[[ -e *.mpg ]]</div>
Globs in regex context
grep '*foo*' file</div>
PS1 colors not in \[..\]
PS1='\e[0;32m\$\e[0m '</div>
Prematurely terminated find -exec
find / -exec touch {} && echo {} \;</div>
Literal quotes in arguments
verbose='--verbose="true"' cmd $verbose</div>
Assignment in subshells
echo foo | read bar echo $bar</div>
Confusing time(1) for builtin
time --format=%s sleep 10</div>
~ in quotes
rm "~/my file.txt"</div>
Single, quoted 'for' argument
for f in "*.ogg" do rm $f; done</div>
Arithmetic truncation
echo $((n/180*100))</div>
Functions used externally
f() { rm file; }; sudo f</div>
Unused variables
var=World; echo "Hello " var</div>
Looping over ls output
for f in $(ls *.ogg) do ...; done</div>
Arguments in aliases
alias archive='mv $1 /backup'</div>
Referencing arrays as strings
files=(foo bar); echo "$files"</div>
Unquoted command expansion
tar cf file$(date).tar dir</div>
$ in for loop variables
for $var in foo bar baz; do echo "$var"; done</div>
Unquoted $@
touch $@
</div> Unicode quotes
rm “file”</div>
Attempted redirection of stdout+stderr
cmd 2>&1 > /dev/null</div>
Attempted indirect assignment
var$n="Hello"</div>
Attempted indirect reference
echo ${var$n}</div>
Variables in single quotes
echo 'Path is $PATH'</div>
Comparing numbers with < or >
[[ $n > 0 ]]</div>
Unsupported [ ] operators
[ foo =~ re ]</div>
Using ~ in $PATH
PATH="$PATH:~/bin"</div>
Quoted =~ regex
[[ $foo =~ "fo+" ]]</div>
Opportunities for
grep -q
[[ -z $(find /tmp | grep mpg) ]]</div>
Tautology due to spacing
[[ $foo==0 ]]</div>
Variable brace expansion (Bash)
echo {1..$n}</div>
Commands eating loop input
while read host; do ssh "$host" uptime; done < file</div>
Decimals arithmetics
echo $((3.14*r*r))</div>
Comma separated arrays
var=(1, 2, 3)</div>
Misused 'exec'
exec foo; echo "Done!"</div>
Globs that could become options
touch ./-l; ls *</div>
Common shebang errors
#!/bin/bash -x -e
</div> Variables in printf format
printf "Hello $name"</div>
Numerical comparison of strings
[[ $1 -eq "shellcheck" ]]</div>
Prefix assignments in args
var=42 echo $var</div>
Implicit precedence in find
find . -name '*.bak' -o -name '*~' -delete</div>
Useless use of echo
echo $(date)</div>
Repetitive redirections
cmd1 >> file; cmd2 >> file; cmd3 >> file;</div>
Redirecting sudo
sudo echo 'alias sl=ls' >> /etc/profile</div>
[] around ranges in tr
tr '[a-z]' '[A-Z]'</div>
Misquoted traps
trap "echo \"Runtime: ${SECONDS}s\"" exit</div>
&& in [ .. ]
[ $n && $m ]</div>
Singlequote closed by apostrophe
echo 'Don't forget to run foo --update!'</div>
Attempting to escape ' in ''
var='Don\'t try this at home'</div>
Misused char class globs
ls *[:digit:].txt</div>
Concatenating strings and arrays.
printf "%s\n" "Command line was $@."</div>
Positional parameter misreference
echo "Argument 10 is $10"</div>
cd-and-back antipattern
for d in *; do cd "$d"; cmd; cd ..; done</div>
Missing semicolons in loops
for f in *.mp3 do true; done</div>
$ in assignments
$foo=42</div>
Aliases expanding early
alias whereami="echo $PWD"</div>
Spaces in assignment
var = 42</div>
Features shebang may not support
#!/bin/sh echo {1..10}</div>
Spurious
$()/``
cmd='echo foo'; `$cmd`;</div>