ShellCheck é uma ferramenta GPLv3 que fornece avisos e sugestões para scripts shell bash/sh:
Os objetivos do ShellCheck são
Apontar e esclarecer problemas típicos de sintaxe para iniciantes que fazem com que um shell forneça mensagens de erro enigmáticas.
Apontar e esclarecer problemas semânticos típicos de nível intermediário que fazem com que um shell se comporte de maneira estranha e contra-intuitiva.
Para apontar advertências sutis, casos extremos e armadilhas que podem fazer com que o script de um usuário avançado falhe em circunstâncias futuras.
Veja a galeria de códigos incorretos para obter exemplos do que o ShellCheck pode ajudá-lo a identificar!
Existem várias maneiras de usar o ShellCheck!
Cole um script de shell em https://www.shellcheck.net para feedback instantâneo.
ShellCheck.net está sempre sincronizado com o commit git mais recente e é a maneira mais fácil de experimentar o ShellCheck. Conte para seus amigos!
Execute shellcheck yourscript
em seu terminal para saída instantânea, como visto acima.
Você pode ver sugestões do ShellCheck diretamente em vários editores.
.
.
Sublime, através do SublimeLinter.
Pulsar Edit (antigo Atom), através de linter-shellcheck-pulsar.
VSCode, por meio de vscode-shellcheck.
A maioria dos outros editores, através da compatibilidade de erros do GCC.
Embora o ShellCheck seja destinado principalmente ao uso interativo, ele pode ser facilmente adicionado a compilações ou suítes de testes. Ele faz uso canônico de códigos de saída, então você pode simplesmente adicionar um comando shellcheck
como parte do processo.
Por exemplo, em um Makefile:
check-scripts :
# Fail if any of these files have warnings
shellcheck myscripts/*.sh
ou em um arquivo Travis CI .travis.yml
:
script :
# Fail if any of these files have warnings
- shellcheck myscripts/*.sh
Serviços e plataformas que possuem ShellCheck pré-instalado e pronto para uso:
A maioria dos outros serviços, incluindo o GitLab, permite que você mesmo instale o ShellCheck, seja por meio do gerenciador de pacotes do sistema (consulte Instalando) ou baixando e descompactando uma versão binária.
É uma boa ideia instalar manualmente uma versão específica do ShellCheck de qualquer maneira. Isso evita interrupções surpresa na compilação quando uma nova versão com novos avisos é publicada.
Para filtragem ou relatórios personalizados, o ShellCheck pode gerar JSON simples, XML compatível com CheckStyle, avisos compatíveis com GCC, bem como texto legível por humanos (com ou sem cores ANSI). Consulte a página wiki de integração para obter mais documentação.
A maneira mais fácil de instalar o ShellCheck localmente é através do gerenciador de pacotes.
Em sistemas com Cabal (instala em ~/.cabal/bin
):
cabal update
cabal install ShellCheck
Em sistemas com Stack (instala em ~/.local/bin
):
stack update
stack install ShellCheck
Em distros baseadas em Debian:
sudo apt install shellcheck
Em distros baseadas em Arch Linux:
pacman -S shellcheck
ou obtenha o shellcheck-bin livre de dependência do AUR.
Em distros baseadas no Gentoo:
emerge --ask shellcheck
Em distros baseadas em EPEL:
sudo yum -y install epel-release
sudo yum install ShellCheck
Em distros baseadas no Fedora:
dnf install ShellCheck
No FreeBSD:
pkg install hs-ShellCheck
No macOS (OS X) com Homebrew:
brew install shellcheck
Ou com MacPorts:
sudo port install shellcheck
No OpenBSD:
pkg_add shellcheck
No openSUSE
zypper in ShellCheck
Ou use OneClickInstall - https://software.opensuse.org/package/ShellCheck
No Solus:
eopkg install shellcheck
No Windows (via chocolate):
C: > choco install shellcheck
Ou Windows (via winget):
C: > winget install --id koalaman.shellcheck
Ou Windows (via furo):
C: > scoop install shellcheck
De conda-forge:
conda install -c conda-forge shellcheck
Da Snap Store:
snap install --channel=edge shellcheck
Do DockerHub:
docker run --rm -v " $PWD :/mnt " koalaman/shellcheck:stable myscript
# Or :v0.4.7 for that version, or :latest for daily builds
ou use koalaman/shellcheck-alpine
se desejar estender uma imagem maior baseada no Alpine Linux. Funciona exatamente como uma imagem Alpine normal, mas possui shellcheck pré-instalado.
Usando o gerenciador de pacotes nix:
nix-env -iA nixpkgs.shellcheck
Usando o gerenciador de pacotes Flox
flox install shellcheck
Alternativamente, você pode baixar binários pré-compilados para a versão mais recente aqui:
ou consulte os lançamentos do GitHub para outros lançamentos (incluindo o meta-lançamento mais recente para compilações diárias do git).
Atualmente não há binários oficiais para Apple Silicon, mas compilações de terceiros estão disponíveis via ShellCheck para Visual Studio Code.
Os pacotes de distribuição já vêm com uma página man
. Se você estiver compilando a partir do código-fonte, ele poderá ser instalado com:
pandoc -s -f markdown-smart -t man shellcheck.1.md -o shellcheck.1
sudo mv shellcheck.1 /usr/share/man/man1
Para executar o ShellCheck via pré-commit, adicione o gancho ao seu .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
O Travis CI agora integrou o ShellCheck por padrão, então você não precisa instalá-lo manualmente.
Se você ainda quiser fazer isso para atualizar quando quiser ou garantir que está usando a versão mais recente, siga as etapas abaixo para instalar uma versão binária.
Os binários pré-compilados vêm em arquivos tar.xz
Para descompactá-los, certifique-se de que xz
esteja instalado. No Debian/Ubuntu/Mint, você pode apt install xz-utils
. No Redhat/Fedora/CentOS, yum -y install xz
.
Um instalador simples pode fazer 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 seção descreve como construir ShellCheck a partir de um diretório de origem. ShellCheck é escrito em Haskell e requer 2 GB de RAM para compilar.
ShellCheck é construído e empacotado usando Cabal. Instale o pacote cabal-install
do gerenciador de pacotes do seu sistema (por exemplo, com apt-get
, brew
, emerge
, yum
ou zypper
).
No macOS (OS X), você pode fazer uma instalação rápida do Cabal usando brew, o que leva alguns minutos em vez de mais de 30 minutos se você tentar compilá-lo a partir do código-fonte.
$ brew install cabal-install
Em MacPorts, o pacote é chamado hs-cabal-install
, enquanto os usuários nativos do Windows devem instalar a versão mais recente da plataforma Haskell em https://www.haskell.org/platform/
Verifique se cabal
está instalado e atualize sua lista de dependências com
$ cabal update
git clone
este repositório e cd
para o diretório de origem do ShellCheck para construir/instalar:
$ cabal install
Isso irá compilar o ShellCheck e instalá-lo em seu diretório ~/.cabal/bin
.
Adicione este diretório ao seu PATH
(para bash, adicione isto ao seu ~/.bashrc
):
export PATH= " $HOME /.cabal/bin: $PATH "
Efetue logout e login novamente e verifique se seu PATH está configurado corretamente:
$ which shellcheck
~ /.cabal/bin/shellcheck
No Windows nativo, o PATH
já deve estar configurado, mas o sistema pode usar uma página de códigos herdada. Em cmd.exe
, powershell.exe
e Powershell ISE, certifique-se de usar uma fonte TrueType, não uma fonte Raster, e defina a página de código ativa como UTF-8 (65001) com chcp
:
chcp 65001
No Powershell ISE, pode ser necessário atualizar adicionalmente a codificação de saída:
[ Console ]::OutputEncoding = [ System.Text.Encoding ]::UTF8
Para executar o conjunto de testes de unidade:
$ cabal test
Então, que tipo de coisas o ShellCheck procura? Aqui está uma lista incompleta de problemas detectados.
ShellCheck pode reconhecer vários tipos de cotações incorretas:
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 pode reconhecer muitos tipos de instruções de teste incorretas.
[[ 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 pode reconhecer instâncias onde os comandos são usados incorretamente:
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 reconhece muitos erros comuns de sintaxe para iniciantes:
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 pode fazer sugestões para melhorar o 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 pode reconhecer problemas relacionados a dados e digitação:
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 pode fazer sugestões para melhorar a robustez de um 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 irá avisar ao usar recursos não suportados pelo shebang. Por exemplo, se você definir o shebang como #!/bin/sh
, o ShellCheck avisará sobre problemas de portabilidade semelhantes aos 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 reconhece uma série de outros 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
No começo você fica tipo "shellcheck é incrível", mas depois você fica tipo "wtf, ainda estamos usando o bash"
Alexander Tarasikov, via Twitter
Os problemas podem ser ignorados por meio de variável ambiental, linha de comando, individual ou globalmente dentro de um arquivo:
https://github.com/koalaman/shellcheck/wiki/Ignorar
Use o rastreador de problemas do GitHub para quaisquer bugs ou sugestões de recursos:
https://github.com/koalaman/shellcheck/issues
Envie patches para código ou documentação como solicitações pull do GitHub! Confira o DevGuide no ShellCheck Wiki.
As contribuições devem ser licenciadas sob a GNU GPLv3. O contribuidor retém os direitos autorais.
ShellCheck está licenciado sob a Licença Pública Geral GNU, v3. Uma cópia desta licença está incluída no arquivo LICENSE.
Copyright 2012-2019, Vidar 'koala_man' Holen e colaboradores.
Feliz ShellChecking!