Códigos de saída
Esta aula aborda os códigos de saída em scripts Bash, incluindo a variável $? que captura o status do último comando, o comando exit para definir o código de saída do script, as convenções de sucesso (0) e falha (1-255), e como encadear comandos baseados no status usando operadores lógicos.
Em scripts Bash, todo comando retorna um código de saída (exit code) quando termina. Esse código é um número inteiro entre 0 e 255 que indica se o comando foi bem-sucedido ou não. Entender e utilizar códigos de saída é fundamental para controlar o fluxo do script, depurar erros e criar programas robustos. Nesta aula, veremos como acessar o código do último comando com $?, como definir o código de saída de um script com exit, as convenções adotadas e como encadear comandos baseados no status.
Dominar esses conceitos permite criar scripts que reagem adequadamente a falhas, evitam execuções desnecessárias e se integram bem com outros programas e pipelines.
$?
A variável especial $? armazena o código de saída do último comando executado no shell. Após cada comando, $? é atualizado automaticamente. Você pode usá-lo para verificar se um comando teve sucesso ou falhou, e tomar decisões condicionais.
Por exemplo, se um comando ls falha porque o diretório não existe, $? será diferente de zero. Você pode testar esse valor com if ou usá-lo em expressões.
#!/bin/bash
ls /diretorio/inexistente
echo "Código de saída: $?"
# Saída: ls: cannot access '/diretorio/inexistente': No such file or directory
# Código de saída: 2
Note que $? é volátil: ele é redefinido a cada comando. Se você precisar usá-lo mais de uma vez, armazene-o em uma variável imediatamente após o comando de interesse.
exit
O comando exit encerra a execução do script e retorna um código de saída para o shell pai. Se nenhum argumento for fornecido, exit retorna o código do último comando executado. É uma boa prática usar exit com um código explícito para indicar o resultado do script.
Por exemplo, um script que valida entrada pode terminar com exit 0 para sucesso e exit 1 para erro.
#!/bin/bash
if [ -z "$1" ]; then
echo "Erro: argumento ausente" >&2
exit 1
fi
echo "Argumento: $1"
exit 0
O código de saída do script pode ser usado por outros scripts ou pelo usuário para saber se tudo ocorreu como esperado.
Convenções (0 = sucesso)
Por convenção, o código de saída 0 indica sucesso, enquanto qualquer valor diferente de zero indica algum tipo de erro. Isso é seguido por praticamente todos os comandos Unix e ferramentas. Os códigos de erro podem ser específicos para cada comando; por exemplo, o comando ls retorna 1 para erros menores (como permissão negada) e 2 para erros graves (como argumento inválido).
Em scripts, você deve seguir essa convenção: retorne 0 quando o script concluir com sucesso, e um código não-zero para falhas. Não há um padrão rígido para o significado de cada número, mas você pode definir seus próprios códigos (por exemplo, 1 para erro genérico, 2 para argumento inválido, 3 para arquivo não encontrado).
#!/bin/bash
# Exemplo de convenção
if [ ! -f "$1" ]; then
echo "Arquivo não encontrado" >&2
exit 3
fi
cat "$1"
exit 0
Encadeando por status
O Bash oferece operadores lógicos que permitem encadear comandos baseados no código de saída do comando anterior. Os mais comuns são && (AND) e || (OR).
comando1 && comando2: executa comando2 somente se comando1 for bem-sucedido (código 0).comando1 || comando2: executa comando2 somente se comando1 falhar (código não-zero).
Esses operadores são úteis para criar sequências condicionais simples sem usar if. Por exemplo:
#!/bin/bash
mkdir /tmp/diretorio && echo "Diretório criado com sucesso"
# Se mkdir falhar (diretório já existe ou permissão negada), o echo não será executado.
ping -c 1 google.com || echo "Falha ao pingar google.com"
# Se ping for bem-sucedido, o echo é ignorado.
Você também pode combinar ambos para criar cadeias mais complexas, mas cuidado com a legibilidade. Para lógica mais elaborada, prefira estruturas if.
Boas Práticas
Sempre verifique o código de saída de comandos críticos, especialmente aqueles que podem falhar (criação de diretórios, cópia de arquivos, etc.). Documente os códigos de saída que seu script utiliza. Use set -e para interromper o script automaticamente se qualquer comando falhar, mas esteja ciente de que isso pode ser muito agressivo. Outra opção é usar trap para capturar erros. Prefira exit 1 a simplesmente deixar o script terminar naturalmente quando ocorrer um erro, para que o chamador saiba que algo deu errado.
Referências
- Bash Manual: Exit Status
- Advanced Bash-Scripting Guide: Exit Status
- Shell Scripting Tutorial: Exit Codes
- Stack Overflow: Standard Exit Status Codes
- nixCraft: Bash Exit Status
- SS64: exit command
Exercícios
-
Escreva um script que tente criar um diretório (com
mkdir) e, se falhar, exiba uma mensagem de erro e saia com código 1. Use$?para verificar o status.✓ Resposta:#!/bin/bash mkdir /tmp/meudir if [ $? -ne 0 ]; then echo "Erro ao criar diretório" >&2 exit 1 fi echo "Diretório criado com sucesso" exit 0 -
Use o operador
&¶ executarecho "sucesso"apenas se o comandols /etc/passwdfor bem-sucedido.✓ Resposta:ls /etc/passwd && echo "sucesso" -
Crie um script que receba um nome de arquivo como argumento. Se o arquivo existir, exiba seu conteúdo e saia com 0. Caso contrário, exiba uma mensagem de erro e saia com 2.
✓ Resposta:
#!/bin/bash if [ -f "$1" ]; then cat "$1" exit 0 else echo "Arquivo não encontrado" >&2 exit 2 fi -
Explique o que o seguinte comando faz:
make && make install || echo "Falha na instalação"✓ Resposta:Executa
make. Se for bem-sucedido (código 0), então executamake install. Semakefalhar,make installnão é executado. Em ambos os casos, após a execução demake install(se ocorreu) ou diretamente após a falha demake, o comandoecho "Falha na instalação"é executado somente se o comando anterior (que émake installoumakecasomake installnão tenha sido executado) falhar. Ou seja, a mensagem aparece semakefalhar ou semake installfalhar. -
Escreva um script que use
exitcom um código de saída personalizado. O script deve verificar se o número de argumentos é igual a 2; se não, saia com código 3. Caso contrário, exiba os argumentos e saia com 0.✓ Resposta:#!/bin/bash if [ $# -ne 2 ]; then echo "Uso: $0 arg1 arg2" >&2 exit 3 fi echo "Argumento 1: $1" echo "Argumento 2: $2" exit 0