Encontrando bugs em shell scripts

- por Sergio Prado

Categorias: Linux Tags: ,

O desenvolvimento de shell scripts deve estar na caixa de ferramentas de todo desenvolvedor e administrador de sistemas Linux.

Por mais simples que possa parecer, é possível fazer coisas bastante malucas e complexas com um shell script, incluindo jogos como este do Mario Bros!

ShellCheck é uma ferramenta de análise estática de código que pode ajudar bastante a encontrar bugs e erros de sintaxe durante o desenvolvimento de shell scripts.

Esta ferramenta foi escrita em Haskell e seu código-fonte está disponível no GitHub sob licença GPLv3.

Está presente nos repositórios da maioria das distribuições GNU/Linux e pode ser instalada normalmente através da ferramenta de gerenciamento de pacotes. No Ubuntu e suas variações, a ferramenta pode ser instalada com o comando abaixo:

$ sudo apt-get install shellcheck

O uso da ferramenta é bem simples. Basta executá-la passando o shell script que você deseja analisar. Como existem algumas pequenas variações de sintaxe entre algumas implementações de shell, é possível definir o dialeto a ser utilizado (bash, sh e ksh) com a opção -s.

$ shellcheck 
No files specified.
 
Usage: shellcheck [OPTIONS...] FILES...
  -e CODE1,CODE2..  --exclude=CODE1,CODE2..  exclude types of warnings
  -f FORMAT         --format=FORMAT          output format
  -s SHELLNAME      --shell=SHELLNAME        Specify dialect (bash,sh,ksh)
  -V                --version                Print version information

Há um tempo escrevi uma ferramenta em shell script chamada mediacreate para automatizar o processo de particionamento, formatação e gravação de imagens em cartões SD. O que será que acontece se eu rodar o ShellCheck neste script?

$ shellcheck mediacreate
 
In mediacreate line 53:
    umount $TMP_DIR 1>/dev/null 2>&1
           ^-- SC2086: Double quote to prevent globbing and word splitting.
 
In mediacreate line 54:
    rm -Rf $TMP_DIR
           ^-- SC2086: Double quote to prevent globbing and word splitting.
 
In mediacreate line 60:
    assert mkdir -p $TMP_DIR
                    ^-- SC2086: Double quote to prevent globbing and word splitting.
 
[...]

Ops! Foram 90 mensagens de erros/warnings! :-)

$ shellcheck mediacreate | grep "In " | wc -l
90

A maioria dos erros está relacionada à ausência de aspas duplas em variáveis para evitar problemas de expansão (SC2086):

In mediacreate line 53:
    umount $TMP_DIR 1>/dev/null 2>&1
           ^-- SC2086: Double quote to prevent globbing and word splitting.

A ferramenta sugere também separar a declaração de variáveis da atribuição para que o retorno do comando na atribuição não seja ignorado (SC2155).

In mediacreate line 244:
    local OPTION_CONFIG=$(get_option_config "GEOMETRY")
          ^-- SC2155: Declare and assign separately to avoid masking return values.

E sugere também o uso de globs ao invés do comando ls para iterar em um conjunto de arquivos (SC2045)

In mediacreate line 335:
    for f in $(ls ${DEVICE_FILE}*); do
             ^-- SC2045: Iterating over ls output is fragile. Use globs.

Existem até plugins para integrar a ferramenta com diversos editores como o Vim, Emacs, Sublime e Atom.

O ShellCheck é realmente uma ferramenta essencial para todo desenvolvedor de shell scripts.

Happy Scripting!

Sergio Prado

  • montalvao

    ShellCheck é bem legal! Vale a pena estudar sua wiki também, com explicações para cada um dos erros. Só com isso dá pra aprender muito!

    Uma sutileza do caso do ls no for: se o arquivo não for encontrado, ele vai retornar vazio no stdout, enquanto o globbing retornaria a própria string (com o *), o que causaria a execução do loop.

    Em tempo: não gosto de usar ls em scripts. ;)

Navegue
Creative Commons Este trabalho de Sergio Prado é licenciado pelo
Creative Commons BY-NC-SA 3.0.