ShellCheck es una herramienta GPLv3 que brinda advertencias y sugerencias para scripts de shell bash/sh:
Los objetivos de ShellCheck son
Señalar y aclarar los problemas de sintaxis típicos de los principiantes que hacen que un shell proporcione mensajes de error crípticos.
Señalar y aclarar problemas semánticos típicos de nivel intermedio que hacen que un shell se comporte de manera extraña y contraintuitiva.
Para señalar advertencias sutiles, casos extremos y trampas que pueden causar que el script de un usuario avanzado falle en circunstancias futuras.
¡Vea la galería de códigos incorrectos para ver ejemplos de lo que ShellCheck puede ayudarle a identificar!
¡Hay varias formas de utilizar ShellCheck!
Pegue un script de shell en https://www.shellcheck.net para obtener comentarios instantáneos.
ShellCheck.net siempre está sincronizado con la última confirmación de git y es la forma más sencilla de probar ShellCheck. ¡Díselo a tus amigos!
Ejecute shellcheck yourscript
en su terminal para obtener una salida instantánea, como se ve arriba.
Puede ver las sugerencias de ShellCheck directamente en una variedad de editores.
.
.
Sublime, a través de SublimeLinter.
Pulsar Edit (antiguo Atom), a través de linter-shellcheck-pulsar.
VSCode, a través de vscode-shellcheck.
La mayoría de los otros editores, a través de la compatibilidad con errores de GCC.
Si bien ShellCheck está diseñado principalmente para uso interactivo, se puede agregar fácilmente a compilaciones o conjuntos de pruebas. Hace uso canónico de códigos de salida, por lo que puedes simplemente agregar un comando shellcheck
como parte del proceso.
Por ejemplo, en un Makefile:
check-scripts :
# Fail if any of these files have warnings
shellcheck myscripts/*.sh
o en un archivo Travis CI .travis.yml
:
script :
# Fail if any of these files have warnings
- shellcheck myscripts/*.sh
Servicios y plataformas que tienen ShellCheck preinstalado y listo para usar:
La mayoría de los demás servicios, incluido GitLab, le permiten instalar ShellCheck usted mismo, ya sea a través del administrador de paquetes del sistema (consulte Instalación) o descargando y descomprimiendo una versión binaria.
Es una buena idea instalar manualmente una versión específica de ShellCheck independientemente. Esto evita interrupciones sorpresa en la compilación cuando se publica una nueva versión con nuevas advertencias.
Para filtrado o informes personalizados, ShellCheck puede generar JSON simple, XML compatible con CheckStyle, advertencias compatibles con GCC, así como texto legible por humanos (con o sin colores ANSI). Consulte la página wiki de integración para obtener más documentación.
La forma más sencilla de instalar ShellCheck localmente es a través del administrador de paquetes.
En sistemas con Cabal (se instala en ~/.cabal/bin
):
cabal update
cabal install ShellCheck
En sistemas con Stack (se instala en ~/.local/bin
):
stack update
stack install ShellCheck
En distribuciones basadas en Debian:
sudo apt install shellcheck
En distribuciones basadas en Arch Linux:
pacman -S shellcheck
u obtenga el shellcheck-bin libre de dependencias de AUR.
En distribuciones basadas en Gentoo:
emerge --ask shellcheck
En distribuciones basadas en EPEL:
sudo yum -y install epel-release
sudo yum install ShellCheck
En distribuciones basadas en Fedora:
dnf install ShellCheck
En FreeBSD:
pkg install hs-ShellCheck
En macOS (OS X) con Homebrew:
brew install shellcheck
O con MacPorts:
sudo port install shellcheck
En OpenBSD:
pkg_add shellcheck
En openSUSE
zypper in ShellCheck
O utilice OneClickInstall: https://software.opensuse.org/package/ShellCheck
Sobre Solus:
eopkg install shellcheck
En Windows (a través de chocolatey):
C: > choco install shellcheck
O Windows (a través de Winget):
C: > winget install --id koalaman.shellcheck
O Windows (a través de primicia):
C: > scoop install shellcheck
De conda-forge:
conda install -c conda-forge shellcheck
De la tienda Snap:
snap install --channel=edge shellcheck
Desde Docker Hub:
docker run --rm -v " $PWD :/mnt " koalaman/shellcheck:stable myscript
# Or :v0.4.7 for that version, or :latest for daily builds
o utilice koalaman/shellcheck-alpine
si desea ampliar una imagen más grande basada en Alpine Linux. Funciona exactamente como una imagen Alpine normal, pero tiene shellcheck preinstalado.
Usando el administrador de paquetes nix:
nix-env -iA nixpkgs.shellcheck
Usando el administrador de paquetes Flox
flox install shellcheck
Alternativamente, puede descargar archivos binarios precompilados para la última versión aquí:
o consulte las versiones de GitHub para conocer otras versiones (incluida la metaversión más reciente para las compilaciones diarias de git).
Actualmente no hay binarios oficiales para Apple Silicon, pero hay compilaciones de terceros disponibles a través de ShellCheck para Visual Studio Code.
Los paquetes de distribución ya vienen con una página man
. Si está compilando desde el código fuente, se puede instalar con:
pandoc -s -f markdown-smart -t man shellcheck.1.md -o shellcheck.1
sudo mv shellcheck.1 /usr/share/man/man1
Para ejecutar ShellCheck mediante confirmación previa, agregue el enlace a su .pre-commit-config.yaml
:
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 ahora ha integrado ShellCheck de forma predeterminada, por lo que no es necesario instalarlo manualmente.
Si aún desea hacerlo para actualizar cuando lo desee o asegurarse de que está utilizando la última versión, siga los pasos a continuación para instalar una versión binaria.
Los binarios precompilados vienen en archivos tar.xz
Para descomprimirlos, asegúrese de que xz
esté instalado. En Debian/Ubuntu/Mint, puede apt install xz-utils
. En Redhat/Fedora/CentOS, yum -y install xz
.
Un instalador sencillo puede hacer algo como:
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
Esta sección describe cómo construir ShellCheck desde un directorio de origen. ShellCheck está escrito en Haskell y requiere 2 GB de RAM para compilarse.
ShellCheck está construido y empaquetado usando Cabal. Instale el paquete cabal-install
desde el administrador de paquetes de su sistema (por ejemplo, con apt-get
, brew
, emerge
, yum
o zypper
).
En macOS (OS X), puedes realizar una instalación rápida de Cabal usando brew, lo que lleva un par de minutos en lugar de más de 30 minutos si intentas compilarlo desde el código fuente.
$ brew install cabal-install
En MacPorts, el paquete se llama hs-cabal-install
, mientras que los usuarios nativos de Windows deben instalar la última versión de la plataforma Haskell desde https://www.haskell.org/platform/
Verifique que cabal
esté instalado y actualice su lista de dependencias con
$ cabal update
git clone
este repositorio y cd
al directorio fuente de ShellCheck para compilar/instalar:
$ cabal install
Esto compilará ShellCheck y lo instalará en su directorio ~/.cabal/bin
.
Agregue este directorio a su PATH
(para bash, agregue esto a su ~/.bashrc
):
export PATH= " $HOME /.cabal/bin: $PATH "
Cierre sesión y vuelva a iniciarla, y verifique que su RUTA esté configurada correctamente:
$ which shellcheck
~ /.cabal/bin/shellcheck
En Windows nativo, la PATH
ya debería estar configurada, pero el sistema puede usar una página de códigos heredada. En cmd.exe
, powershell.exe
y Powershell ISE, asegúrese de utilizar una fuente TrueType, no una fuente Raster, y configure la página de códigos activa en UTF-8 (65001) con chcp
:
chcp 65001
En Powershell ISE, es posible que necesite actualizar adicionalmente la codificación de salida:
[ Console ]::OutputEncoding = [ System.Text.Encoding ]::UTF8
Para ejecutar el conjunto de pruebas unitarias:
$ cabal test
Entonces, ¿qué tipo de cosas busca ShellCheck? Aquí hay una lista incompleta de problemas detectados.
ShellCheck puede reconocer varios tipos de citas incorrectas:
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 puede reconocer muchos tipos de declaraciones de prueba incorrectas.
[[ 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 puede reconocer casos en los que los comandos se utilizan incorrectamente:
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 reconoce muchos errores de sintaxis comunes para principiantes:
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 puede hacer sugerencias para mejorar el estilo:
[[ -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 puede reconocer problemas relacionados con los datos y la escritura:
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 puede hacer sugerencias para mejorar la solidez de un script:
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 advertirá cuando se utilicen funciones no compatibles con Shebang. Por ejemplo, si configura el shebang en #!/bin/sh
, ShellCheck advertirá sobre problemas de portabilidad similares a 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 reconoce una serie de otros problemas:
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
Al principio dices "shellcheck es increíble", pero luego dices "wtf, ¿todavía usamos bash?"
Alexander Tarasikov, vía Twitter
Los problemas se pueden ignorar mediante una variable ambiental, una línea de comando, de forma individual o global dentro de un archivo:
https://github.com/koalaman/shellcheck/wiki/Ignore
Utilice el rastreador de problemas de GitHub para detectar errores o sugerencias de funciones:
https://github.com/koalaman/shellcheck/issues
¡Envíe parches para el código o la documentación como solicitudes de extracción de GitHub! Consulte la DevGuide en ShellCheck Wiki.
Las contribuciones deben tener licencia GNU GPLv3. El colaborador conserva los derechos de autor.
ShellCheck tiene la licencia pública general GNU, v3. Una copia de esta licencia se incluye en el archivo LICENCIA.
Copyright 2012-2019, Vidar 'koala_man' Holen y colaboradores.
¡Feliz ShellChecking!