Skip to main content

Shell Scripting

  • Shell Scripting

Guia rápido: como criar um shell script no Linux


1) O que é um shell script?

Um shell script é um arquivo de texto com comandos do shell (geralmente Bash) executados em sequência. Serve para automatizar tarefas, backups, deploys, relatórios, etc.


2) Pré‑requisitos

  • Um Linux com Bash (quase todas as distros têm por padrão)
  • Um editor de texto: nano, vim, ou um editor gráfico
  • Acesso ao terminal

3) Passo a passo (primeiro script)

  1. Crie um arquivo, por exemplo ola.sh:

    nano ola.sh
  2. Coloque o conteúdo básico:

    #!/usr/bin/env bash
    # Script de exemplo: imprime uma saudação
    echo "Olá, mundo!"

    Shebang (#!/usr/bin/env bash): indica ao sistema qual interpretador usar.

  3. Salve e saia (no nano: Ctrl+O, Enter, Ctrl+X).

  4. Dê permissão de execução:

    chmod +x ola.sh
  5. Execute:

    ./ola.sh

    Se falhar com “Permissão negada”, verifique as permissões ou use bash ola.sh.


4) Estrutura típica de um script

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

# === Metadados ===
# Nome: meu_script.sh
# Descrição: Faz X, Y, Z
# Uso: ./meu_script.sh [opções]
# Autor: Seu Nome
# Versão: 1.0.0

# === Funções auxiliares ===
log() { printf '[%s] %s\n' "$(date +'%Y-%m-%d %H:%M:%S')" "$*"; }
abort() { printf 'Erro: %s\n' "$*" >&2; exit 1; }

# === Validação de requisitos ===
command -v curl >/dev/null 2>&1 || abort "curl não encontrado"

# === Lógica principal ===
main() {
log "Iniciando…"
# Seu código aqui
log "Concluído."
}

main "$@"

Explicações:

  • set -euo pipefail: falha ao primeiro erro, erro de variável não definida (-u) e encadeamentos (pipefail).
  • IFS seguro: evita surpresas com espaços em nomes de arquivos.
  • main "$@": repassa argumentos para a função principal.

5) Variáveis e argumentos

  • Definição: nome="Ana"

  • Uso: echo "Olá, $nome"

  • Posicionais: $0 (nome do script), $1, $2, …, $# (quantos), $@ (todos)

  • Exemplo:

    #!/usr/bin/env bash
    set -euo pipefail
    nome=${1:-mundo}
    echo "Olá, $nome!"

    Uso: ./ola.sh Ana

Dica: sempre cite variáveis com aspas: "$var".


6) Leitura interativa

read -rp "Digite seu nome: " nome
printf 'Olá, %s!\n' "$nome"

7) Condicionais e testes

if [[ -f arquivo.txt ]]; then
echo "arquivo existe"
elif [[ -d arquivo.txt ]]; then
echo "é diretório"
else
echo "não existe"
fi

# Comparações numéricas
if (( 3 > 2 )); then echo "maior"; fi

# Comparações de strings
if [[ "$user" == "root" ]]; then echo "admin"; fi

8) Loops

# for sobre lista
for f in *.log; do
echo "Processando $f"
gzip -9 "$f"
done

# while lendo arquivo com segurança
while IFS= read -r linha; do
echo "$linha"
done < input.txt

9) Funções

soma() { echo $(( $1 + $2 )); }
resultado=$(soma 2 5)
echo "$resultado"

10) Entrada/saída, redirecionamento e pipes

  • > sobrescreve, >> acrescenta
  • 2> stderr, &> stdout+stderr
  • Exemplo: comando >saida.txt 2>erros.log
  • Pipes: ls -l | grep "\.sh$" | wc -l

11) Códigos de saída

  • 0 = sucesso; 1..255 = erros
  • Último status: $?
  • Sair explicitamente: exit 42

12) Depuração

  • set -x para rastrear comandos
  • Ad-hoc: bash -x script.sh
  • Logs com timestamps (ver função log acima)

13) Tratamento de erros

set -euo pipefail
trap 'echo "Falhou na linha $LINENO" >&2' ERR

cria_dir() {
local dir=$1
[[ -d "$dir" ]] || mkdir -p "$dir"
}

14) Processamento de opções (getopts)

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

usage() {
cat <<EOF
Uso: ${0##*/} [-n NOME] [-v]
-n NOME Nome para saudar
-v Modo verboso
EOF
}

nome="mundo"; verbose=false

while getopts ":n:v" opt; do
case "$opt" in
n) nome=$OPTARG ;;
v) verbose=true ;;
:) echo "Faltou argumento para -$OPTARG" >&2; usage; exit 2 ;;
\?) echo "Opção inválida: -$OPTARG" >&2; usage; exit 2 ;;
esac
done
shift $((OPTIND-1))

$verbose && echo "Saudando…"
echo "Olá, $nome!"

15) Arrays

frutas=(maçã banana uva)
echo "Primeira: ${frutas[0]}"
for f in "${frutas[@]}"; do echo "$f"; done

16) Boas práticas rápidas

  • Use #!/usr/bin/env bash, não sh, se usar recursos Bash
  • set -euo pipefail em scripts não-interativos
  • Cite variáveis: "$var"
  • Use "${var:-default}" para valores padrão
  • Prefira [[ ]] a [ ] para testes
  • Evite caminhos absolutos de comandos; valide com command -v
  • Trate erros e use trap quando fizer sentido
  • Escreva usage e --help
  • Formate com shellcheck (linter) quando possível

17) Agendamento com cron (opcional)

  1. Edite o crontab:

    crontab -e
  2. Exemplo: executar todo dia às 03:30:

    30 3 * * * /caminho/para/backup.sh >> /var/log/backup.log 2>&1

18) Template reutilizável

#!/usr/bin/env bash
# shellcheck disable=SC2155
set -euo pipefail
IFS=$'\n\t'

readonly SCRIPT_NAME=${0##*/}
readonly SCRIPT_DIR=$(cd -- "${BASH_SOURCE[0]%/*}" && pwd)

usage() {
cat <<EOF
Uso: $SCRIPT_NAME [opções]
Opções:
-h, --help Mostra esta ajuda
-o ARQ Arquivo de saída (padrão: stdout)
EOF
}

out=""

parse_args() {
while [[ ${1-} ]]; do
case "$1" in
-h|--help) usage; exit 0 ;;
-o) shift; out=${1-""} ;;
*) echo "Argumento desconhecido: $1" >&2; usage; exit 2 ;;
esac
shift || true
done
}

main() {
parse_args "$@"
local msg="Olá do $SCRIPT_NAME"
if [[ -n "$out" ]]; then
printf '%s\n' "$msg" >"$out"
else
printf '%s\n' "$msg"
fi
}

main "$@"

19) Exemplo prático: compactar logs antigos

#!/usr/bin/env bash
set -euo pipefail
shopt -s nullglob

LOG_DIR=${1:-/var/log/meuapp}
DIAS=${2:-7}

find "$LOG_DIR" -type f -name '*.log' -mtime +"$DIAS" -print0 \
| xargs -0 -I{} gzip -9 {}

Uso: ./compacta_logs.sh /caminho/dos/logs 14