O que voce vai aprender neste tutorial
- Estrutura basica de shell scripts
- Como usar variaveis
- Condicionais (if)
- Loops (for, while)
- Scripts praticos de automacao
O que e Shell Script? Por que aprender?
A origem do Shell Script
A historia do shell script remonta a 1971 com o Thompson shell (sh). Em 1979, Stephen Bourne desenvolveu o Bourne Shell (sh), que se tornou a base dos shell scripts modernos.
Em 1989, Brian Fox desenvolveu o Bash (Bourne Again Shell) como parte do projeto GNU. Bash e atualmente o shell mais amplamente utilizado.
“Shell script e a forma mais simples de automatizar tarefas repetitivas” — Sabedoria antiga do ambiente Unix
Por que aprender Shell Script
- Automacao: Automatize tarefas repetitivas e economize tempo
- Administracao de sistemas: Essencial para gerenciamento de servidores, deploy e backup
- CI/CD: Amplamente usado no GitHub Actions, Jenkins, etc.
- Portabilidade: Funciona em praticamente todos os sistemas Unix
Bash e outros Shells
| Shell | Caracteristicas | Uso principal |
|---|---|---|
| bash | Mais difundido. Compativel com POSIX + extensoes | Scripts gerais |
| sh | Padrao POSIX. Funcionalidade minima | Scripts com foco em portabilidade |
| zsh | Compativel com bash + autocompletar poderoso | Shell interativo |
| fish | Amigavel ao usuario | Shell interativo |
| dash | Leve e rapido | Scripts de sistema |
Melhores praticas: Use
#!/bin/shpara portabilidade, e#!/bin/bashquando usar recursos especificos do Bash.
Seu primeiro Shell Script
Vamos comecar com o “Hello World”.
hello.sh
#!/bin/bash
# Este e meu primeiro shell script
echo "Hello, World!"
Como executar
# Dar permissao de execucao
chmod +x hello.sh
# Executar
./hello.sh
# Ou especificar bash explicitamente
bash hello.sh
Sobre o Shebang
A primeira linha #!/bin/bash e chamada de shebang e especifica qual interpretador vai executar o script.
#!/bin/bash # Executar com bash
#!/bin/sh # Executar com POSIX sh (mais portavel)
#!/usr/bin/env bash # Procurar bash no PATH e executar (recomendado)
Documentacao oficial: GNU Bash Manual
Como usar variaveis
Variaveis basicas
#!/bin/bash
# Definir variaveis (sem espacos ao redor do =!)
name="Joao"
age=25
# Referenciar variaveis
echo "Nome: $name"
echo "Idade: ${age} anos"
# Atribuir resultado de comando a uma variavel
current_date=$(date +%Y-%m-%d)
echo "Data de hoje: $current_date"
# Forma antiga (crase) - nao recomendado
old_style=`date +%Y-%m-%d`
Erro comum: Espacos
# Errado (espacos causam erro)
name = "Joao" # command not found: name
name= "Joao" # Variavel vazia como comando "Joao" executado
# Correto
name="Joao"
Escopo de variaveis
#!/bin/bash
# Variavel global
global_var="I am global"
function example() {
# Variavel local (valida apenas dentro da funcao)
local local_var="I am local"
echo "$local_var"
echo "$global_var"
}
example
echo "$local_var" # Vazio (nao visivel fora da funcao)
Variaveis especiais
#!/bin/bash
echo "Nome do script: $0"
echo "Primeiro argumento: $1"
echo "Segundo argumento: $2"
echo "Numero de argumentos: $#"
echo "Todos os argumentos: $@"
echo "Todos os argumentos (string): $*"
echo "Status de saida do ultimo comando: $?"
echo "PID do processo atual: $$"
echo "PID do processo em background: $!"
Exemplo de execucao:
$ ./script.sh arg1 arg2 arg3
Nome do script: ./script.sh
Primeiro argumento: arg1
Segundo argumento: arg2
Numero de argumentos: 3
Todos os argumentos: arg1 arg2 arg3
Variaveis de ambiente
# Referenciar variaveis de ambiente
echo "Diretorio home: $HOME"
echo "Nome do usuario: $USER"
echo "Diretorio atual: $PWD"
echo "Shell: $SHELL"
echo "Path: $PATH"
# Definir variavel de ambiente (herdada por subprocessos)
export MY_VAR="some value"
# Definir variavel de ambiente temporariamente para executar comando
DEBUG=true ./my_script.sh
Diferenca entre aspas
name="World"
# Aspas duplas: variaveis sao expandidas
echo "Hello, $name" # Hello, World
# Aspas simples: literal
echo 'Hello, $name' # Hello, $name
# Escape com barra invertida
echo "Hello, \$name" # Hello, $name
Condicionais (if)
Sintaxe basica
#!/bin/bash
age=20
if [ $age -ge 20 ]; then
echo "E adulto"
elif [ $age -ge 13 ]; then
echo "E adolescente"
else
echo "E crianca"
fi
Tipos de sintaxe de teste
# [ ] - Sintaxe test classica (compativel com POSIX)
if [ $a -eq $b ]; then
# [[ ]] - Sintaxe estendida do Bash (recomendada)
if [[ $a == $b ]]; then
# (( )) - Avaliacao aritmetica
if (( a > b )); then
Melhores praticas: Ao usar Bash, recomenda-se
[[ ]]. Permite pattern matching e expressoes regulares.
Operadores de comparacao numerica
| Operador | Significado | Exemplo |
|---|---|---|
-eq | Igual (equal) | [ $a -eq $b ] |
-ne | Diferente (not equal) | [ $a -ne $b ] |
-lt | Menor que (less than) | [ $a -lt $b ] |
-le | Menor ou igual (less or equal) | [ $a -le $b ] |
-gt | Maior que (greater than) | [ $a -gt $b ] |
-ge | Maior ou igual (greater or equal) | [ $a -ge $b ] |
Comparacao de strings
#!/bin/bash
str="hello"
# Comparacao de strings (importante usar aspas!)
if [ "$str" = "hello" ]; then
echo "Strings sao iguais"
fi
# Verificar string vazia
if [ -z "$str" ]; then
echo "String esta vazia"
fi
# Verificar se nao esta vazia
if [ -n "$str" ]; then
echo "String nao esta vazia"
fi
# Pattern matching com [[ ]]
if [[ "$str" == h* ]]; then
echo "Comeca com h"
fi
# Expressao regular (Bash 3.0+)
if [[ "$str" =~ ^[a-z]+$ ]]; then
echo "Apenas letras minusculas"
fi
Verificacao de arquivos e diretorios
#!/bin/bash
# Verificar existencia de arquivo
if [ -f "config.txt" ]; then
echo "config.txt existe"
fi
# Verificar existencia de diretorio
if [ -d "logs" ]; then
echo "Diretorio logs existe"
fi
# Arquivo ou diretorio existe
if [ -e "path" ]; then
echo "path existe"
fi
# Legivel
if [ -r "file.txt" ]; then
echo "E legivel"
fi
# Gravavel
if [ -w "file.txt" ]; then
echo "E gravavel"
fi
# Executavel
if [ -x "script.sh" ]; then
echo "E executavel"
fi
# Arquivo nao esta vazio
if [ -s "file.txt" ]; then
echo "Arquivo nao esta vazio"
fi
Operadores logicos
# AND
if [ $a -gt 0 ] && [ $a -lt 10 ]; then
echo "0 < a < 10"
fi
# OR
if [ $a -eq 0 ] || [ $a -eq 1 ]; then
echo "a is 0 or 1"
fi
# NOT
if [ ! -f "file.txt" ]; then
echo "file.txt does not exist"
fi
# [[ ]] permite && e || internamente
if [[ $a -gt 0 && $a -lt 10 ]]; then
echo "0 < a < 10"
fi
Instrucao case
Para multiplas condicoes, a instrucao case e conveniente:
#!/bin/bash
fruit="apple"
case $fruit in
apple)
echo "E uma maca"
;;
banana|orange)
echo "E banana ou laranja"
;;
*)
echo "Fruta desconhecida"
;;
esac
Loops
Loop for
#!/bin/bash
# Processar lista em ordem
for fruit in apple banana orange; do
echo "Fruta: $fruit"
done
# Intervalo numerico (extensao Bash)
for i in {1..5}; do
echo "Contagem: $i"
done
# Especificar incremento
for i in {0..10..2}; do
echo "Par: $i"
done
# Estilo C
for ((i=0; i<5; i++)); do
echo "Index: $i"
done
# Processar arquivos
for file in *.txt; do
echo "Arquivo: $file"
done
# Processar saida de comando
for user in $(cat users.txt); do
echo "Usuario: $user"
done
Loop while
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Contagem: $count"
count=$((count + 1))
done
# Ler arquivo linha por linha (padrao recomendado)
while IFS= read -r line; do
echo "Linha: $line"
done < input.txt
# Loop infinito
while true; do
echo "Press Ctrl+C to stop"
sleep 1
done
Loop until
#!/bin/bash
count=1
until [ $count -gt 5 ]; do
echo "Contagem: $count"
count=$((count + 1))
done
Controle de loop
# break para sair do loop
for i in {1..10}; do
if [ $i -eq 5 ]; then
break
fi
echo $i
done
# continue para proxima iteracao
for i in {1..5}; do
if [ $i -eq 3 ]; then
continue
fi
echo $i
done
Definicao de funcoes
#!/bin/bash
# Definicao de funcao (duas formas)
function greet() {
local name=$1
echo "Ola, ${name}!"
}
# Ou
greet2() {
echo "Hello, $1!"
}
# Chamar funcao
greet "Joao"
greet2 "World"
# Valor de retorno (status de saida)
is_even() {
if (( $1 % 2 == 0 )); then
return 0 # Sucesso (par)
else
return 1 # Falha (impar)
fi
}
if is_even 4; then
echo "4 e par"
fi
# Para retornar valor, use echo
add() {
echo $(( $1 + $2 ))
}
result=$(add 3 5)
echo "3 + 5 = $result"
Pratica: Script de Backup
Usando o que aprendemos, vamos criar um script de backup pratico.
backup.sh
#!/bin/bash
#
# Script de backup automatico
# Uso: ./backup.sh [source_dir] [backup_dir]
#
set -euo pipefail # Sair imediatamente em caso de erro
# Configuracao
SOURCE_DIR="${1:-./src}"
BACKUP_DIR="${2:-./backups}"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_$DATE.tar.gz"
RETENTION_DAYS=7
# Funcao de log
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# Verificar/criar diretorio de backup
if [ ! -d "$BACKUP_DIR" ]; then
log "Criando diretorio de backup..."
mkdir -p "$BACKUP_DIR"
fi
# Verificar diretorio de origem
if [ ! -d "$SOURCE_DIR" ]; then
log "Erro: $SOURCE_DIR nao encontrado"
exit 1
fi
# Executar backup
log "Iniciando backup: $SOURCE_DIR -> $BACKUP_DIR/$BACKUP_NAME"
tar -czf "$BACKUP_DIR/$BACKUP_NAME" "$SOURCE_DIR"
if [ $? -eq 0 ]; then
log "Concluido: $BACKUP_DIR/$BACKUP_NAME"
log "Tamanho: $(du -h "$BACKUP_DIR/$BACKUP_NAME" | cut -f1)"
else
log "Erro: Falha no backup"
exit 1
fi
# Remover backups antigos
log "Removendo backups antigos (mais de ${RETENTION_DAYS} dias)..."
deleted=$(find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete -print | wc -l)
log "Arquivos removidos: $deleted"
log "Tudo concluido!"
Melhores praticas para scripts
-
Use
set -euo pipefail-e: Sair imediatamente em caso de erro-u: Erro para variaveis indefinidas-o pipefail: Detectar erros em pipes
-
Sempre use aspas em variaveis:
"$variable" -
Use funcoes: Melhor reusabilidade e legibilidade
-
Adicione logs: Para debug e monitoramento
Tratamento de erros
#!/bin/bash
# Definir tratamento de erro com trap
cleanup() {
echo "Executando limpeza..."
# Remover arquivos temporarios, etc.
}
trap cleanup EXIT # Executar ao sair do script
trap 'echo "Erro ocorrido: linha $LINENO"' ERR
# Ignorar erro se necessario
command_that_might_fail || true
# Tratamento alternativo em caso de erro
config_file="config.txt"
if [ -f "$config_file" ]; then
source "$config_file"
else
echo "Arquivo de configuracao nao encontrado. Usando valores padrao."
default_value="fallback"
fi
Dicas de Debug
# Executar script inteiro em modo debug
bash -x script.sh
# Ativar debug dentro do script
set -x # Iniciar debug
# ... codigo para debug ...
set +x # Parar debug
# Sair imediatamente em caso de erro (recomendado)
set -e
# Erro para variaveis indefinidas (recomendado)
set -u
# Detectar erros em pipes (recomendado)
set -o pipefail
# Combinacao comum
set -euo pipefail
Analise estatica com ShellCheck
ShellCheck e uma ferramenta de analise estatica que detecta problemas em shell scripts.
# Instalacao
# macOS
brew install shellcheck
# Ubuntu/Debian
sudo apt install shellcheck
# Uso
shellcheck script.sh
Exemplos de problemas detectados pelo ShellCheck:
# Aviso: falta de aspas na variavel
echo $USER # SC2086: Double quote to prevent globbing
# Corrigido
echo "$USER"
O Google Shell Style Guide tambem recomenda o uso do ShellCheck.
Padroes comuns
Validacao de argumentos
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Uso: $0 <source> <destination>"
exit 1
fi
source=$1
destination=$2
Definicao de valores padrao
# Usar valor padrao se variavel nao definida ou vazia
name="${1:-World}"
echo "Hello, $name"
# Usar valor padrao apenas se variavel nao definida
name="${1-World}"
Criacao segura de arquivos temporarios
#!/bin/bash
# Usar mktemp (recomendado)
temp_file=$(mktemp)
temp_dir=$(mktemp -d)
# Remover ao sair
trap "rm -rf $temp_file $temp_dir" EXIT
echo "Arquivo temporario: $temp_file"
echo "Diretorio temporario: $temp_dir"
Obtendo entrada do usuario
#!/bin/bash
# Ler entrada
read -p "Digite seu nome: " name
echo "Ola, $name"
# Entrada de senha (oculta)
read -sp "Senha: " password
echo ""
# Com timeout
read -t 5 -p "Digite em 5 segundos: " input || echo "Timeout"
Proximos passos
Apos dominar o basico de shell script, avance para os proximos passos:
- Expressoes regulares e
grep,sed,awk - Execucao agendada com cron jobs
- Automacao mais avancada (Ansible, Makefile, etc.)
Links de referencia
Documentacao oficial
- GNU Bash Manual - Referencia oficial do Bash
- POSIX Shell Command Language - Padrao POSIX
Guias de estilo e melhores praticas
- Google Shell Style Guide - Guia de estilo do Google para shell scripts
- ShellCheck - Ferramenta de analise estatica para shell scripts
Recursos de aprendizado
- Bash Hackers Wiki - Tecnicas avancadas de Bash
- explainshell.com - Explica comandos inseridos
- Pure Bash Bible - Colecao de receitas implementadas apenas em Bash
Cheat sheets
- Bash Scripting Cheat Sheet - Lista de sintaxes comuns
- Advanced Bash-Scripting Guide - Guia detalhado de Bash (ingles)