fbpx Shell Script Avanzado: Funciones, Arrays y Errores en Bash | Certificação Linux

Shell Script Avanzado: Funciones, Arrays y Manejo de Errores

📅 19/07/2026 ⏱ 4 min ✍️ Uira Ribeiro
Shell Script Avanzado: Funciones, Arrays y Manejo de Errores
Exam Pass App — mais de 7.000 questões LPI, offline, em 5 idiomas, disponível no Android e na App Store
Disponible en
Google Play
Disponible en
App Store

Los scripts Bash son el pegamento de la administración de sistemas Linux. Pero existe una diferencia enorme entre un script que funciona una vez y un script que puede ejecutarse en producción a las 3 de la mañana sin explotar el servidor. Este artículo cubre las técnicas que hacen esa diferencia.

La Cabecera Obligatoria de Todo Script Serio

#!/usr/bin/env bash
set -euo pipefail

# -e : sai imediatamente se qualquer comando retornar erro
# -u : trata variáveis não definidas como erro (evita $VAZIO virar "")
# -o pipefail : propaga erro em pipes (cmd1 | cmd2 → falha se cmd1 falha)

Sin estos tres flags, tu script continúa en silencio después de un rm -rf que falló o una variable vacía que destruye una ruta de archivo.

Funciones

#!/usr/bin/env bash
set -euo pipefail

# Convenção: funções de log com timestamp
log()  { echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO:  $*"; }
warn() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARN:  $*" >&2; }
die()  { echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERRO:  $*" >&2; exit 1; }

# Função com retorno de valor
soma() {
    local a=$1 b=$2     # local: variável não vaza para o escopo global
    echo $(( a + b ))
}

resultado=$(soma 3 7)
log "3 + 7 = $resultado"

# Função que verifica dependências
requer() {
    for cmd in "$@"; do
        command -v "$cmd" &>/dev/null || die "Comando não encontrado: $cmd"
    done
}

requer curl jq aws

Arreglos

#!/usr/bin/env bash
set -euo pipefail

# Array indexado
servidores=("web01" "web02" "db01" "cache01")

# Iterar
for srv in "${servidores[@]}"; do
    echo "Verificando $srv..."
done

# Número de elementos
echo "Total: ${#servidores[@]}"

# Slice (índices 1 e 2)
echo "${servidores[@]:1:2}"   # → web02 db01

# Array associativo (dicionário)
declare -A config
config[host]="localhost"
config[porta]="5432"
config[banco]="producao"

for chave in "${!config[@]}"; do
    echo "$chave = ${config[$chave]}"
done

# Ler linhas de um arquivo para array
mapfile -t linhas < /etc/hosts
echo "Linhas em /etc/hosts: ${#linhas[@]}"

Procesando Argumentos con getopts

#!/usr/bin/env bash
set -euo pipefail

uso() {
    cat <<EOF
Uso: $0 [-h] [-v] [-e AMBIENTE] [-n NOME]

  -h           Mostra esta ajuda
  -v           Modo verbose
  -e AMBIENTE  Ambiente (dev|stg|prod)   [obrigatório]
  -n NOME      Nome do deploy            [padrão: app]
EOF
    exit 1
}

VERBOSE=0
AMBIENTE=""
NOME="app"

while getopts ":hve:n:" opt; do
    case $opt in
        h) uso ;;
        v) VERBOSE=1 ;;
        e) AMBIENTE=$OPTARG ;;
        n) NOME=$OPTARG ;;
        :) die "Opção -$OPTARG requer argumento" ;;
        ?) die "Opção inválida: -$OPTARG" ;;
    esac
done

[[ -z "$AMBIENTE" ]] && die "-e AMBIENTE é obrigatório"
[[ "$AMBIENTE" =~ ^(dev|stg|prod)$ ]] || die "Ambiente inválido: $AMBIENTE"

echo "Deploy de '$NOME' em '$AMBIENTE'"
[[ $VERBOSE -eq 1 ]] && echo "[verbose] Detalhes adicionais aqui"

Manejo de Errores con trap

#!/usr/bin/env bash
set -euo pipefail

TMPDIR=$(mktemp -d)

# Cleanup automático ao sair (com erro ou não)
cleanup() {
    local codigo=$?
    rm -rf "$TMPDIR"
    [[ $codigo -ne 0 ]] && echo "Script falhou com código $codigo" >&2
}
trap cleanup EXIT

# Se o script morrer por sinal (Ctrl+C, kill), limpar antes
trap 'echo "Interrompido" >&2; exit 130' INT TERM

echo "Arquivos temporários em $TMPDIR"
# ... seu trabalho aqui ...
# TMPDIR é removido automaticamente ao sair

Logging a Archivo

#!/usr/bin/env bash
set -euo pipefail

LOGFILE="/var/log/meu-script.log"
LOGDIR=$(dirname "$LOGFILE")
mkdir -p "$LOGDIR"

# Redirecionar stdout e stderr para o log E para o terminal
exec > >(tee -a "$LOGFILE") 2>&1

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }

log "=== Iniciando script $(basename "$0") ==="
log "Usuário: $(whoami) | PID: $$"

Verificaciones de Seguridad Esenciales

# Verificar se está rodando como root
[[ $EUID -eq 0 ]] || die "Este script precisa ser root"

# Verificar se arquivo existe antes de usar
[[ -f "$CONFIG" ]] || die "Arquivo não encontrado: $CONFIG"

# Evitar race condition com lock file
LOCKFILE="/tmp/meu-script.lock"
exec 200>"$LOCKFILE"
flock -n 200 || die "Outra instância já está rodando"

# Validar que variável não está vazia E é numérica
[[ "${PORTA:-}" =~ ^[0-9]+$ ]] || die "PORTA deve ser numérica"

# Aspas duplas SEMPRE em variáveis (evita word splitting)
arquivo="meu arquivo com espaços.txt"
rm -f "$arquivo"   # correto
# rm -f $arquivo   # errado: vira 'rm -f meu arquivo com espaços.txt' → 4 args

Template de Script de Producción

#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
LOGFILE="/var/log/$(basename "$0" .sh).log"

exec > >(tee -a "$LOGFILE") 2>&1

log()  { echo "[$(date '+%F %T')] INFO  $*"; }
warn() { echo "[$(date '+%F %T')] WARN  $*" >&2; }
die()  { echo "[$(date '+%F %T')] ERRO  $*" >&2; exit 1; }

cleanup() { log "Finalizado (código: $?)"; }
trap cleanup EXIT

main() {
    log "Iniciando — args: $*"
    # seu código aqui
}

main "$@"

Este template ya tiene logging, cleanup automático, propagación de error y paso de argumentos a la función main. Copia, adapta y usa como base para cualquier script nuevo.

Uira Ribeiro

Prof. Uirá Ribeiro

Chair do Board do Linux Professional Institute

Después de años viendo profesionales perder horas en tareas simples por no conocer las herramientas correctas de Linux, decidí enseñar.
Hoy soy autor de la mayoría de los Materiales de Aprendizaje oficiales de la LPI y mentor de más de 14,000 alumnos certificados.

Conoce mi historia completa →

Eso fue solo una pieza. El curso enseña el camino completo — desde tu primer comando hasta el día del examen.

Certificação Linux — a plataforma líder em certificações Linux no Brasil
WhatsApp