Códigos de saída
Nesta aula, você aprenderá sobre códigos de saída em scripts Bash: como usar $? para capturar o status do último comando, como definir códigos com exit, as convenções de 0 para sucesso e valores diferentes de zero para erros, e como encadear comandos baseados no status de saída.
Em scripts Bash, todo comando executado retorna um código numérico ao finalizar, chamado de código de saída (ou exit status). Este código é fundamental para controle de fluxo, tratamento de erros e automação. Nesta aula, exploraremos como acessar, definir e utilizar esses códigos para criar scripts mais robustos e confiáveis.
O código de saída é um inteiro entre 0 e 255. Por convenção, o valor 0 indica sucesso, enquanto qualquer valor diferente de zero indica algum tipo de falha. O shell armazena o código do último comando executado em uma variável especial $?, permitindo que você tome decisões baseadas no resultado.
$?
A variável $? contém o código de saída do último comando executado em primeiro plano. Ela é atualizada a cada comando, então você deve consultá-la imediatamente após o comando de interesse, antes de executar outro.
Exemplo prático:
#!/bin/bash
ls /etc/passwd
echo "Código de saída: $?"
ls /arquivo_inexistente
echo "Código de saída: $?"Saída esperada:
/etc/passwd
Código de saída: 0
ls: cannot access '/arquivo_inexistente': No such file or directory
Código de saída: 2Note que o ls bem-sucedido retorna 0, enquanto o que falha retorna 2 (código comum para erro de arquivo não encontrado).
exit
O comando exit encerra o script atual e retorna um código de saída para o shell pai. Você pode usar exit com um número específico ou sem argumentos (que retorna o código do último comando). É uma boa prática usar exit 0 para sucesso e exit 1 (ou outros) para falhas.
Exemplo:
#!/bin/bash
if [ ! -f "$1" ]; then
echo "Erro: arquivo $1 não encontrado."
exit 1
fi
cat "$1"
exit 0Se o arquivo passado como argumento não existir, o script imprime uma mensagem e termina com código 1. Caso contrário, exibe o conteúdo e sai com 0.
Convenções (0 = sucesso)
A convenção universal em sistemas Unix/Linux é: código 0 = sucesso, qualquer outro = falha. Não use 0 para indicar erro, pois isso quebra a compatibilidade com ferramentas padrão. Códigos comuns incluem:
- 0: sucesso
- 1: erro genérico
- 2: uso incorreto (ex.: sintaxe inválida)
- 126: comando encontrado mas não executável
- 127: comando não encontrado
- 130: script interrompido por Ctrl+C (sinal 2)
- 255: código inválido (fora do range 0-255)
Respeitar essas convenções permite que outros scripts e ferramentas (como make, CI/CD) interpretem corretamente seus resultados.
Encadeando por status
O Bash oferece operadores lógicos para encadear comandos baseados no código de saída:
comando1 && comando2: executacomando2apenas secomando1retornar 0 (sucesso).comando1 || comando2: executacomando2apenas secomando1retornar diferente de 0 (falha).comando1 ; comando2: executacomando2independentemente do resultado (sequencial).
Exemplo:
#!/bin/bash
# Cria diretório e, se bem-sucedido, copia arquivo
mkdir -p /tmp/meu_dir && cp /etc/hosts /tmp/meu_dir/ || echo "Falha na operação"Se o mkdir falhar (ex.: permissão negada), o cp não será executado e a mensagem de erro será exibida.
Você também pode usar if para verificar explicitamente:
if comando; then
echo "Sucesso"
else
echo "Falha com código $?"
fiBoas práticas
- Sempre defina códigos de saída explícitos com
exitem funções e scripts. - Documente os códigos de saída usados (ex.: 1 para erro de argumento, 2 para erro de arquivo).
- Use
set -epara interromper o script ao primeiro erro, mas com cuidado. - Evite códigos de saída ambíguos; prefira mensagens de erro claras no stderr.
Referências
- GNU Bash Manual: Exit Status
- Advanced Bash-Scripting Guide: Exit Status
- man bash (Linux Die.net)
- Shell Scripting Tutorial: Exit Codes
- nixCraft: How to set exit status in Bash
Exercícios
Crie um script que verifique se o usuário atual é 'root'. Se for, exiba "Root detectado" e saia com código 0; caso contrário, exiba "Não é root" e saia com código 1.
✓ Resposta:#!/bin/bash if [ "$(id -u)" -eq 0 ]; then echo "Root detectado" exit 0 else echo "Não é root" exit 1 fiEscreva um comando (não script) que tente criar um diretório e, se bem-sucedido, navegue para ele; caso contrário, exiba "Falha". Use operadores && e ||.
✓ Resposta:mkdir /tmp/teste && cd /tmp/teste || echo "Falha"O que será impresso pelo seguinte script? Explique.
#!/bin/bash true echo $? false echo $?✓ Resposta:O script imprime 0 e 1. O comandotruesempre retorna 0 (sucesso), então $? é 0. O comandofalsesempre retorna 1 (falha), então $? é 1.Escreva um script que aceite um nome de arquivo como argumento. Se o arquivo existir e for legível, exiba seu conteúdo e saia com 0. Caso contrário, exiba uma mensagem de erro apropriada e saia com um código diferente de zero (use 1 para não existente, 2 para sem permissão).
✓ Resposta:#!/bin/bash if [ $# -eq 0 ]; then echo "Uso: $0 arquivo" >&2 exit 2 fi if [ ! -e "$1" ]; then echo "Erro: arquivo $1 não existe." >&2 exit 1 fi if [ ! -r "$1" ]; then echo "Erro: sem permissão de leitura para $1." >&2 exit 2 fi cat "$1" exit 0Explique a diferença entre os seguintes comandos e o que cada um faz com base no código de saída:
comando1 && comando2 || comando3✓ Resposta:O comando executacomando1. Secomando1retornar 0 (sucesso), entãocomando2é executado. Secomando2também retornar 0, o||não executacomando3. Secomando1falhar (retorno != 0),&&impedecomando2e o||executacomando3. Secomando1for bem-sucedido mascomando2falhar, o||também executarácomando3(porque o resultado geral do&&foi falha).