Esta é uma pergunta antiga, mas nenhuma das respostas aqui discute o uso de set -e
aka set -o errexit
nos scripts de manipulação de pacotes Debian. O uso desta opção é obrigatório nesses scripts, de acordo com a política Debian; aparentemente, a intenção é evitar qualquer possibilidade de uma condição de erro não tratado.
O que isso significa na prática é que você precisa entender sob quais condições os comandos executados podem retornar um erro e tratar explicitamente cada um desses erros.
Os truques comuns são, por exemplo, diff
(retorna um erro quando há uma diferença) e grep
(retorna um erro quando não há correspondência). Você pode evitar os erros com manipulação explícita:
diff this that ||
echo "$0: there was a difference" >&2
grep cat food ||
echo "$0: no cat in the food" >&2
(Observe também como tomamos o cuidado de incluir o nome do script atual na mensagem e gravar mensagens de diagnóstico em erro padrão em vez de saída padrão.)
Se nenhum tratamento explícito for realmente necessário ou útil, não faça nada explicitamente:
diff this that || true
grep cat food || :
(O uso do :
comando no-op do shell é um pouco obscuro, mas geralmente visto.)
Apenas para reiterar,
something || other
é uma abreviação de
if something; then
: nothing
else
other
fi
ou seja, dizemos explicitamente que other
deve ser executado se e somente se something
falhar. A mão longa if
(e outras instruções de controle de fluxo do shell como while
, until
) também é uma maneira válida de lidar com um erro (de fato, se não fosse, os scripts do shell set -e
nunca poderiam conter instruções de controle de fluxo!)
E também, apenas para ser explícito, na ausência de um manipulador como esse, set -e
faria com que o script inteiro falhasse imediatamente com um erro se diff
encontrasse uma diferença ou se grep
não encontrasse uma correspondência.
Por outro lado, alguns comandos não produzem um status de saída de erro quando você deseja. Os comandos geralmente problemáticos são find
(o status de saída não reflete se os arquivos foram realmente encontrados) e sed
(o status de saída não revela se o script recebeu alguma entrada ou se executou algum comando com êxito). Uma proteção simples em alguns cenários é canalizar para um comando que grita se não houver saída:
find things | grep .
sed -e 's/o/me/' stuff | grep ^
Deve-se observar que o status de saída de um pipeline é o status de saída do último comando nesse pipeline. Portanto, os comandos acima mascaram completamente o status de find
e sed
, e apenas informam se grep
finalmente foi bem-sucedido.
(É claro que o Bash tem set -o pipefail
; mas os scripts de pacotes do Debian não podem usar os recursos do Bash. A política dita firmemente o uso do POSIX sh
para esses scripts, embora esse nem sempre tenha sido o caso.)
Em muitas situações, isso é algo a ser observado separadamente ao codificar na defensiva. Às vezes, você precisa, por exemplo, passar por um arquivo temporário para ver se o comando que produziu essa saída foi concluído com êxito, mesmo quando o idioma e a conveniência o direcionariam a usar um pipeline de shell.