Guia Prático de Shell Script no Linux [Com Exemplos Reais 2026]

O Shell Script é uma das habilidades mais valorizadas e indispensáveis para qualquer administrador de sistemas Linux, engenheiro de DevOps, analista de infraestrutura ou estudante focado em exames como Linux Essentials (010-160) e LPIC-1. Com a automação em Bash, rotinas repetitivas de manutenção, auditoria de segurança, rotação de logs e backup que levariam horas podem ser executadas e agendadas com precisão milimétrica em poucos segundos.

Neste guia prático, detalhado e estruturado para o padrão de produção de 2026, você aprenderá a arquitetura fundamental do interpretador Bash, manipulação de variáveis, operadores de teste, estruturas de repetição, funções modulares, captura de sinais do sistema e verá dois scripts completos e funcionais prontos para rodar no seu servidor.

1. A Anatomia Básica e Boas Práticas de Engenharia em Shell Script

Todo script executável em ambiente Unix deve iniciar com o Shebang (#!/bin/bash) na primeira linha absoluta do arquivo. O Shebang indica ao carregador de programas do kernel qual interpretador de comandos deve ser chamado para analisar as instruções subsequentes.

Para construir scripts de nível corporativo e evitar comportamentos imprevisíveis, é altamente recomendado declarar o modo estrito de execução logo abaixo do cabeçalho:

💡 O Modo Estrito de Execução (Strict Mode): A linha set -euo pipefail é considerada o padrão-ouro no desenvolvimento em Bash:

  • set -e: Interrompe o script imediatamente se qualquer comando retornar um código de saída diferente de zero (erro).
  • set -u: Gera um erro fatal se o script tentar utilizar uma variável que não foi declarada anteriormente.
  • set -o pipefail: Faz com que um encadeamento de pipes (ex: cmd1 | cmd2 | cmd3) falhe se qualquer um dos comandos falhar, e não apenas o último.

Antes de executar qualquer script no Linux, lembre-se de que o arquivo recém-criado possui apenas permissões de leitura e escrita. Você deve conceder a permissão de execução usando o comando chmod +x nome_do_script.sh, conforme abordamos no guia completo de Permissões no Linux (chmod e chown).

#!/bin/bash
# ==========================================================
# Script: diagnostico_sistema.sh
# Finalidade: Auditoria rápida de recursos do servidor
# Autor: Jonas Oliveira - TecMestre (2026)
# ==========================================================
set -euo pipefail

NOME_HOST=$(hostname)
UPTIME=$(uptime -p)
IP_LOCAL=$(hostname -I | awk '{print $1}')
MEMORIA_LIVRE=$(free -h | awk '/^Mem:/ {print $4}')
DISCO_LIVRE=$(df -h / | awk 'NR==2 {print $4}')

echo "=========================================================="
echo "📊 RELATÓRIO DO SERVIDOR: $NOME_HOST ($IP_LOCAL)"
echo "⏱️ Tempo em atividade: $UPTIME"
echo "💾 Memória RAM Disponível: $MEMORIA_LIVRE"
echo "💽 Espaço em Disco Livre na Raiz: $DISCO_LIVRE"
echo "📅 Auditoria executada em: $(date +'%d/%m/%Y às %H:%M:%S')"
echo "=========================================================="

2. Manipulação de Variáveis, Argumentos e Variáveis Especiais

No interpretador Bash, a declaração de variáveis não tolera espaços ao redor do sinal de igual (use sempre DIRETORIO="/var/log" e nunca DIRETORIO = "/var/log"). Para recuperar o valor contido em uma variável, utilize o prefixo $ ou a forma explícita com chaves ${VARIAVEL}.

Ao interagir com a linha de comando, o Bash fornece variáveis especiais reservadas para captura de argumentos passados na chamada do script:

Variável EspecialFunção e Descrição TécnicaExemplo no Terminal
$0Retorna o nome do arquivo do próprio script em execução../deploy_stack.sh
$1, $2 ... $9Parâmetros posicionais passados pelo operador ao invocar o script.$1 = "nginx", $2 = "porta80"
$#Quantidade numérica total de argumentos passados na linha de comando.if [ $# -lt 2 ]; then...
$@ e $*Todos os argumentos passados reunidos em uma única lista ou array.for param in "$@"; do
$$PID (Process ID) do próprio script em execução no sistema.echo $$ > /var/run/meu.pid
$?Código de retorno do último comando (0 = Sucesso; >0 = Código de Erro).if [ $? -eq 0 ]; then...

3. Estruturas Condicionais Avançadas (if, elif, else e case)

As tomadas de decisão são a base de qualquer lógica de automação. No Bash moderno, o operador de colchetes duplos [[ ... ]] é preferível em relação ao teste POSIX simples [ ... ] por suportar operadores lógicos compostos (&&, ||) e expressões regulares sem a necessidade de escape de aspas.

Operador de TesteCondição Avaliada como Verdadeira
-f "caminho"O caminho aponta para um arquivo existente e regular.
-d "caminho"O caminho aponta para um diretório existente.
-z "$VAR"A string da variável possui comprimento zero (está vazia).
-n "$VAR"A string da variável NÃO está vazia (comprimento maior que zero).
-eq, -ne, -gt, -ltComparação numérica (Igual, Diferente, Maior que, Menor que).
==, !=Comparação léxica de strings e padrões de texto.
#!/bin/bash
# Exemplo de estrutura condicional com validação de privilégios root
if [[ $EUID -ne 0 ]]; then
    echo "❌ Erro: Este script precisa ser executado com privilégios de superusuário (sudo)."
    exit 1
fi

SERVICO="nginx"
if systemctl is-active --quiet "$SERVICO"; then
    echo "✅ O serviço $SERVICO está operando normalmente."
else
    echo "⚠️ O serviço $SERVICO está inativo! Tentando reiniciar..."
    systemctl restart "$SERVICO"
fi

4. Estruturas de Repetição (Loops for, while e Leitura Linha por Linha)

Os loops permitem processar listas massivas de arquivos, ranges numéricos ou realizar leituras linha a linha de relatórios e saídas de comandos:

#!/bin/bash
# Loop para monitorar e compactar logs antigos com mais de 10MB
DIRETORIO_LOGS="/var/log/nginx"

for log_file in "$DIRETORIO_LOGS"/*.log; do
    if [[ -f "$log_file" ]]; then
        tamanho_mb=$(du -m "$log_file" | cut -f1)
        if [[ $tamanho_mb -gt 10 ]]; then
            echo "📦 Compactando $log_file (${tamanho_mb}MB)..."
            gzip -9 "$log_file"
        fi
    fi
done

# Leitura segura de arquivo linha a linha sem pular a última linha
ARQUIVO_IPS="/etc/servidores_alvo.txt"
if [[ -f "$ARQUIVO_IPS" ]]; then
    while IFS= read -r ip || [[ -n "$ip" ]]; do
        echo "📡 Testando conectividade com o nó: $ip"
        ping -c 1 -W 2 "$ip" > /dev/null 2>&1 && echo "   ✅ $ip Online" || echo "   ❌ $ip Inacessível"
    done < "$ARQUIVO_IPS"
fi

5. Script Completo de Produção: Backup Automatizado com Rotação e Log

Abaixo está a arquitetura completa de um script profissional de backup para servidores web Linux, incluindo criação de diretórios, cálculo de tempo de execução, log de auditoria e rotação que remove arquivos com mais de 7 dias:

#!/bin/bash
# ==============================================================
# Script: backup_producao_tecmestre.sh
# Autor: Jonas Oliveira - TecMestre
# ==============================================================
set -euo pipefail

# Definições de Caminhos e Parâmetros
DIR_ORIGEM="/www/wwwroot/tecmestre.com.br"
DIR_DESTINO="/backup/diario/tecmestre"
TIMESTAMP=$(date +'%Y-%m-%d_%H%M%S')
NOME_ARQUIVO="tecmestre_backup_${TIMESTAMP}.tar.gz"
CAMINHO_FINAL="${DIR_DESTINO}/${NOME_ARQUIVO}"
ARQUIVO_LOG="/var/log/backup_rotina_tecmestre.log"

# Função para escrita padronizada de logs
log_msg() {
    local mensagem="$1"
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $mensagem" | tee -a "$ARQUIVO_LOG"
}

# Criar diretório de destino se não existir
mkdir -p "$DIR_DESTINO"

log_msg "🚀 [INÍCIO] Iniciando rotina de backup de: $DIR_ORIGEM"

# Executar compactação ignorando diretórios de cache temporário
if tar --exclude='*/wp-content/cache/*' 
       --exclude='*/wp-content/litespeed/*' 
       -czf "$CAMINHO_FINAL" -C "$(dirname "$DIR_ORIGEM")" "$(basename "$DIR_ORIGEM")"; then
    
    TAMANHO_GERADO=$(du -h "$CAMINHO_FINAL" | awk '{print $1}')
    log_msg "✅ Arquivo gerado com sucesso: $NOME_ARQUIVO (Tamanho: $TAMANHO_GERADO)"
else
    log_msg "❌ ERRO CRÍTICO ao gerar o arquivo compactado de backup!"
    exit 2
fi

# Executar rotação de retenção (remover arquivos com mais de 7 dias)
log_msg "🧹 [ROTAÇÃO] Removendo backups com mais de 7 dias de retenção..."
find "$DIR_DESTINO" -type f -name "tecmestre_backup_*.tar.gz" -mtime +7 -exec rm -f {} ;

log_msg "🎉 [FIM] Rotina de backup e rotação finalizada com sucesso."

🎓 100% Gratuito

Treine seus conhecimentos de Linux e Cloud

Acesse nosso simulador interativo com timer oficial de prova, gabarito comentado e estatísticas de acerto em tempo real.

6. Perguntas Frequentes (FAQ)

Qual a diferença entre #!/bin/bash e #!/bin/sh?

O /bin/sh é o interpretador de comandos padrão POSIX básico, enquanto o /bin/bash suporta recursos avançados como arrays, expressões regulares e operadores estendidos [[ ]].

Como agendar um script para rodar automaticamente toda madrugada no Linux?

Abra o agendador de tarefas digitando crontab -e no terminal e adicione a linha: 0 3 * * * /root/backup.sh para rodar todo dia às 03:00 da manhã.

Por que usar set -euo pipefail no início de scripts Bash?

Essa diretriz é uma boa prática de engenharia que força o script a parar imediatamente se qualquer comando falhar ou se uma variável não declarada for executada.

Avatar de Jonas Oliveira
Especialista em Infraestrutura de TI, Linux, Redes e Computação em Nuvem (AWS & Oracle Cloud). Fundador e autor técnico no TecMestre.