ShellCheck ist ein GPLv3-Tool, das Warnungen und Vorschläge für Bash/Sh-Shell-Skripte ausgibt:
Die Ziele von ShellCheck sind
Um typische Syntaxprobleme für Anfänger aufzuzeigen und zu klären, die dazu führen, dass eine Shell kryptische Fehlermeldungen ausgibt.
Aufzeigen und Klären typischer semantischer Probleme auf mittlerer Ebene, die dazu führen, dass sich eine Shell seltsam und kontraintuitiv verhält.
Um auf subtile Vorbehalte, Eckfälle und Fallstricke hinzuweisen, die dazu führen können, dass das ansonsten funktionierende Skript eines fortgeschrittenen Benutzers unter zukünftigen Umständen fehlschlägt.
Sehen Sie sich die Galerie mit fehlerhaftem Code an, um Beispiele dafür zu finden, was ShellCheck Ihnen bei der Identifizierung helfen kann!
Es gibt verschiedene Möglichkeiten, ShellCheck zu verwenden!
Fügen Sie ein Shell-Skript auf https://www.shellcheck.net ein, um sofortiges Feedback zu erhalten.
ShellCheck.net wird immer mit dem neuesten Git-Commit synchronisiert und ist die einfachste Möglichkeit, ShellCheck auszuprobieren. Sag es deinen Freunden!
Führen Sie shellcheck yourscript
in Ihrem Terminal aus, um eine sofortige Ausgabe zu erhalten, wie oben gezeigt.
Sie können ShellCheck-Vorschläge direkt in verschiedenen Editoren anzeigen.
.
.
Erhaben, durch SublimeLinter.
Pulsar Edit (ehemals Atom), über linter-shellcheck-pulsar.
VSCode, über vscode-Shellcheck.
Die meisten anderen Editoren verfügen über GCC-Fehlerkompatibilität.
Während ShellCheck hauptsächlich für die interaktive Nutzung gedacht ist, kann es problemlos zu Builds oder Testsuiten hinzugefügt werden. Exit-Codes werden standardmäßig verwendet, sodass Sie als Teil des Prozesses einfach einen shellcheck
-Befehl hinzufügen können.
Zum Beispiel in einem Makefile:
check-scripts :
# Fail if any of these files have warnings
shellcheck myscripts/*.sh
oder in einer Travis CI .travis.yml
Datei:
script :
# Fail if any of these files have warnings
- shellcheck myscripts/*.sh
Dienste und Plattformen, auf denen ShellCheck vorinstalliert und einsatzbereit ist:
Bei den meisten anderen Diensten, einschließlich GitLab, können Sie ShellCheck selbst installieren, entweder über den Paketmanager des Systems (siehe Installieren) oder durch Herunterladen und Entpacken einer Binärversion.
Es ist trotzdem eine gute Idee, eine bestimmte ShellCheck-Version manuell zu installieren. Dadurch werden überraschende Build-Unterbrechungen vermieden, wenn eine neue Version mit neuen Warnungen veröffentlicht wird.
Für individuelle Filterung oder Berichte kann ShellCheck einfache JSON-, CheckStyle-kompatible XML- und GCC-kompatible Warnungen sowie für Menschen lesbaren Text (mit oder ohne ANSI-Farben) ausgeben. Weitere Dokumentation finden Sie auf der Integrations-Wiki-Seite.
Der einfachste Weg, ShellCheck lokal zu installieren, ist über Ihren Paketmanager.
Auf Systemen mit Cabal (wird unter ~/.cabal/bin
installiert):
cabal update
cabal install ShellCheck
Auf Systemen mit Stack (Installation unter ~/.local/bin
):
stack update
stack install ShellCheck
Auf Debian-basierten Distributionen:
sudo apt install shellcheck
Auf Arch Linux-basierten Distributionen:
pacman -S shellcheck
oder holen Sie sich den abhängigkeitsfreien Shellcheck-bin von der AUR.
Auf Gentoo-basierten Distributionen:
emerge --ask shellcheck
Auf EPEL-basierten Distributionen:
sudo yum -y install epel-release
sudo yum install ShellCheck
Auf Fedora-basierten Distributionen:
dnf install ShellCheck
Auf FreeBSD:
pkg install hs-ShellCheck
Unter macOS (OS X) mit Homebrew:
brew install shellcheck
Oder mit MacPorts:
sudo port install shellcheck
Auf OpenBSD:
pkg_add shellcheck
Auf openSUSE
zypper in ShellCheck
Oder verwenden Sie OneClickInstall – https://software.opensuse.org/package/ShellCheck
Auf Solus:
eopkg install shellcheck
Unter Windows (über Chocolatey):
C: > choco install shellcheck
Oder Windows (über Winget):
C: > winget install --id koalaman.shellcheck
Oder Windows (über Scoop):
C: > scoop install shellcheck
Von conda-forge:
conda install -c conda-forge shellcheck
Aus dem Snap Store:
snap install --channel=edge shellcheck
Vom Docker Hub:
docker run --rm -v " $PWD :/mnt " koalaman/shellcheck:stable myscript
# Or :v0.4.7 for that version, or :latest for daily builds
oder verwenden Sie koalaman/shellcheck-alpine
wenn Sie ein größeres, auf Alpine Linux basierendes Image erweitern möchten. Es funktioniert genau wie ein normales Alpine-Image, jedoch ist Shellcheck vorinstalliert.
Verwendung des Nix-Paketmanagers:
nix-env -iA nixpkgs.shellcheck
Verwendung des Flox-Paketmanagers
flox install shellcheck
Alternativ können Sie hier vorkompilierte Binärdateien für die neueste Version herunterladen:
oder sehen Sie sich die GitHub-Releases für andere Releases an (einschließlich der neuesten Meta-Release für tägliche Git-Builds).
Derzeit gibt es keine offiziellen Binärdateien für Apple Silicon, aber Builds von Drittanbietern sind über ShellCheck für Visual Studio Code verfügbar.
Distributionspakete enthalten bereits eine man
. Wenn Sie aus dem Quellcode erstellen, kann es mit Folgendem installiert werden:
pandoc -s -f markdown-smart -t man shellcheck.1.md -o shellcheck.1
sudo mv shellcheck.1 /usr/share/man/man1
Um ShellCheck per Pre-Commit auszuführen, fügen Sie den Hook zu Ihrer .pre-commit-config.yaml
hinzu:
repos:
- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.7.2
hooks:
- id: shellcheck
# args: ["--severity=warning"] # Optionally only show errors and warnings
Travis CI hat ShellCheck jetzt standardmäßig integriert, sodass Sie es nicht manuell installieren müssen.
Wenn Sie dies dennoch tun möchten, um in Ruhe ein Upgrade durchzuführen oder sicherzustellen, dass Sie die neueste Version verwenden, führen Sie die folgenden Schritte aus, um eine Binärversion zu installieren.
Die vorkompilierten Binärdateien liegen in tar.xz
Dateien vor. Um sie zu dekomprimieren, stellen Sie sicher, dass xz
installiert ist. Unter Debian/Ubuntu/Mint können Sie apt install xz-utils
. Unter Redhat/Fedora/CentOS: yum -y install xz
.
Ein einfacher Installer könnte so etwas tun:
scversion= " stable " # or "v0.4.7", or "latest"
wget -qO- " https://github.com/koalaman/shellcheck/releases/download/ ${scversion?} /shellcheck- ${scversion?} .linux.x86_64.tar.xz " | tar -xJv
cp " shellcheck- ${scversion} /shellcheck " /usr/bin/
shellcheck --version
In diesem Abschnitt wird beschrieben, wie Sie ShellCheck aus einem Quellverzeichnis erstellen. ShellCheck ist in Haskell geschrieben und benötigt zum Kompilieren 2 GB RAM.
ShellCheck wird mit Cabal erstellt und verpackt. Installieren Sie das Paket cabal-install
über den Paketmanager Ihres Systems (z. B. mit apt-get
, brew
, emerge
, yum
oder zypper
).
Unter macOS (OS
$ brew install cabal-install
Auf MacPorts heißt das Paket stattdessen hs-cabal-install
, während native Windows-Benutzer die neueste Version der Haskell-Plattform von https://www.haskell.org/platform/ installieren sollten.
Stellen Sie sicher, dass cabal
installiert ist, und aktualisieren Sie seine Abhängigkeitsliste mit
$ cabal update
git clone
dieses Repository und wechselt cd
zum ShellCheck-Quellverzeichnis, um Folgendes zu erstellen/installieren:
$ cabal install
Dadurch wird ShellCheck kompiliert und in Ihrem ~/.cabal/bin
-Verzeichnis installiert.
Fügen Sie dieses Verzeichnis zu Ihrem PATH
hinzu (fügen Sie es für Bash zu Ihrem ~/.bashrc
hinzu):
export PATH= " $HOME /.cabal/bin: $PATH "
Melden Sie sich ab und wieder an und überprüfen Sie, ob Ihr PATH richtig eingerichtet ist:
$ which shellcheck
~ /.cabal/bin/shellcheck
Unter nativem Windows sollte der PATH
bereits eingerichtet sein, das System verwendet jedoch möglicherweise eine ältere Codepage. Stellen Sie in cmd.exe
, powershell.exe
und Powershell ISE sicher, dass Sie eine TrueType-Schriftart und keine Rasterschriftart verwenden, und legen Sie die aktive Codepage mit chcp
auf UTF-8 (65001) fest:
chcp 65001
In Powershell ISE müssen Sie möglicherweise zusätzlich die Ausgabekodierung aktualisieren:
[ Console ]::OutputEncoding = [ System.Text.Encoding ]::UTF8
So führen Sie die Unit-Test-Suite aus:
$ cabal test
Nach welchen Dingen sucht ShellCheck? Hier ist eine unvollständige Liste der erkannten Probleme.
ShellCheck kann verschiedene Arten falscher Zitate erkennen:
echo $1 # Unquoted variables
find . -name * .ogg # Unquoted find/grep patterns
rm " ~/my file.txt " # Quoted tilde expansion
v= ' --verbose="true" ' ; cmd $v # Literal quotes in variables
for f in " *.ogg " # Incorrectly quoted 'for' loops
touch $@ # Unquoted $@
echo ' Don ' t forget to restart ! ' # Singlequote closed by apostrophe
echo ' Don ' t try this at home ' # Attempting to escape ' in ' '
echo ' Path is $PATH ' # Variables in single quotes
trap " echo Took ${SECONDS} s " 0 # Prematurely expanded trap
unset var[i] # Array index treated as glob
ShellCheck kann viele Arten falscher Testanweisungen erkennen.
[[ n != 0 ]] # Constant test expressions
[[ -e * .mpg ]] # Existence checks of globs
[[ $foo == 0 ]] # Always true due to missing spaces
[[ -n " $foo " ]] # Always true due to literals
[[ $foo =~ " fo+ " ]] # Quoted regex in =~
[ foo =~ re ] # Unsupported [ ] operators
[ $1 -eq " shellcheck " ] # Numerical comparison of strings
[ $n && $m ] # && in [ .. ]
[ grep -q foo file ] # Command without $(..)
[[ " $$ file " == * .jpg ]] # Comparisons that can't succeed
(( 1 - lt 2 )) # Using test operators in ((..))
[ x ] & [ y ] | [ z ] # Accidental backgrounding and piping
ShellCheck kann Fälle erkennen, in denen Befehle falsch verwendet werden:
grep ' *foo* ' file # Globs in regex contexts
find . -exec foo {} && bar {} ; # Prematurely terminated find -exec
sudo echo ' Var=42 ' > /etc/profile # Redirecting sudo
time --format=%s sleep 10 # Passing time(1) flags to time builtin
while read h ; do ssh " $h " uptime # Commands eating while loop input
alias archive= ' mv $1 /backup ' # Defining aliases with arguments
tr -cd ' [a-zA-Z0-9] ' # [] around ranges in tr
exec foo ; echo " Done! " # Misused 'exec'
find -name * .bak -o -name * ~ -delete # Implicit precedence in find
# find . -exec foo > bar ; # Redirections in find
f () { whoami ; }; sudo f # External use of internal functions
ShellCheck erkennt viele häufige Syntaxfehler für Anfänger:
var = 42 # Spaces around = in assignments
$foo =42 # $ in assignments
for $var in * ; do ... # $ in for loop variables
var $n = " Hello " # Wrong indirect assignment
echo ${var $n } # Wrong indirect reference
var=(1, 2, 3) # Comma separated arrays
array=( [index] = value ) # Incorrect index initialization
echo $var [14] # Missing {} in array references
echo " Argument 10 is $1 0 " # Positional parameter misreference
if $( myfunction ) ; then .. ; fi # Wrapping commands in $()
else if othercondition ; then .. # Using 'else if'
f ; f () { echo " hello world; } # Using function before definition
[ false ] # 'false' being true
if ( -f file ) # Using (..) instead of test
ShellCheck kann Vorschläge zur Verbesserung des Stils machen:
[[ -z $( find /tmp | grep mpg ) ]] # Use grep -q instead
a >> log ; b >> log ; c >> log # Use a redirection block instead
echo " The time is ` date ` " # Use $() instead
cd dir ; process * ; cd .. ; # Use subshells instead
echo $[1+2] # Use standard $((..)) instead of old $[]
echo $(( $RANDOM % 6 )) # Don't use $ on variables in $((..))
echo " $( date ) " # Useless use of echo
cat file | grep foo # Useless use of cat
ShellCheck kann Probleme im Zusammenhang mit Daten und Eingaben erkennen:
args= " $@ " # Assigning arrays to strings
files=(foo bar) ; echo " $files " # Referencing arrays as strings
declare -A arr=(foo bar) # Associative arrays without index
printf " %sn " " Arguments: $@ . " # Concatenating strings and arrays
[[ $# > 2 ]] # Comparing numbers as strings
var=World ; echo " Hello " var # Unused lowercase variables
echo " Hello $name " # Unassigned lowercase variables
cmd | read bar ; echo $bar # Assignments in subshells
cat foo | cp bar # Piping to commands that don't read
printf ' %s: %sn ' foo # Mismatches in printf argument count
eval " ${array[@]} " # Lost word boundaries in array eval
for i in " ${x[@]} " ; do ${x[$i]} # Using array value as key
ShellCheck kann Vorschläge zur Verbesserung der Robustheit eines Skripts machen:
rm -rf " $STEAMROOT / " * # Catastrophic rm
touch ./-l ; ls * # Globs that could become options
find . -exec sh -c ' a && b {} ' ; # Find -exec shell injection
printf " Hello $name " # Variables in printf format
for f in $( ls * .txt ) ; do # Iterating over ls output
export MYVAR= $( cmd ) # Masked exit codes
case $version in 2. * ) : ;; 2.6. * ) # Shadowed case branches
ShellCheck warnt, wenn Funktionen verwendet werden, die vom Shebang nicht unterstützt werden. Wenn Sie den Shebang beispielsweise auf #!/bin/sh
setzen, warnt ShellCheck vor Portabilitätsproblemen, ähnlich wie bei checkbashisms
:
echo {1.. $n } # Works in ksh, but not bash/dash/sh
echo {1..10} # Works in ksh and bash, but not dash/sh
echo -n 42 # Works in ksh, bash and dash, undefined in sh
expr match str regex # Unportable alias for `expr str : regex`
trap ' exit 42 ' sigint # Unportable signal spec
cmd & > file # Unportable redirection operator
read foo < /dev/tcp/host/22 # Unportable intercepted files
foo-bar () { .. ; } # Undefined/unsupported function name
[ $UID = 0 ] # Variable undefined in dash/sh
local var=value # local is undefined in sh
time sleep 1 | sleep 5 # Undefined uses of 'time'
ShellCheck erkennt eine Vielzahl weiterer Probleme:
PS1= ' e[0;32m$e[0m ' # PS1 colors not in [..]
PATH= " $PATH :~/bin " # Literal tilde in $PATH
rm “file” # Unicode quotes
echo " Hello world " # Carriage return / DOS line endings
echo hello # Trailing spaces after
var=42 echo $var # Expansion of inlined environment
! # bin/bash -x -e # Common shebang errors
echo $(( n / 180 * 100 )) # Unnecessary loss of precision
ls * [:digit:].txt # Bad character class globs
sed ' s/foo/bar/ ' file > file # Redirecting to input
var2= $var2 # Variable assigned to itself
[ x $var = xval ] # Antiquated x-comparisons
ls () { ls -l " $@ " ; } # Infinitely recursive wrapper
alias ls= ' ls -l ' ; ls foo # Alias used before it takes effect
for x ; do for x ; do # Nested loop uses same variable
while getopts " a " f ; do case $f in " b " ) # Unhandled getopts flags
Zuerst denkst du: „Shellcheck ist großartig“, aber dann denkst du: „Wtf, verwenden wir immer noch Bash?“
Alexander Tarasikov, über Twitter
Probleme können über Umgebungsvariablen, Befehlszeile, einzeln oder global innerhalb einer Datei ignoriert werden:
https://github.com/koalaman/shellcheck/wiki/Ignore
Bitte verwenden Sie den GitHub-Issue-Tracker für etwaige Fehler oder Funktionsvorschläge:
https://github.com/koalaman/shellcheck/issues
Bitte reichen Sie Patches für Code oder Dokumentation als GitHub-Pull-Requests ein! Schauen Sie sich den DevGuide im ShellCheck Wiki an.
Beiträge müssen unter der GNU GPLv3 lizenziert sein. Das Urheberrecht liegt beim Mitwirkenden.
ShellCheck ist unter der GNU General Public License, v3, lizenziert. Eine Kopie dieser Lizenz ist in der Datei LIZENZ enthalten.
Copyright 2012-2019, Vidar 'koala_man' Holen und Mitwirkende.
Viel Spaß beim ShellChecking!