Criando uma Aplicação do Mundo Real
Agora que aprendemos sobre variáveis, variáveis não definidas, expansão de parâmetros e modo estrito, vamos combinar todos esses conceitos em um script prático. Criaremos um utilitário simples de backup de arquivos que demonstra as melhores práticas para lidar com variáveis em Bash.
Planejando Nosso Script de Backup
Nosso script de backup irá:
- Receber um diretório de origem e um destino de backup como entradas
- Permitir a configuração por meio de variáveis de ambiente ou argumentos de linha de comando
- Lidar com erros de forma elegante usando o modo estrito
- Fornecer feedback útil ao usuário
Criando o Script de Backup
- Crie um novo arquivo chamado
backup.sh com o seguinte conteúdo:
#!/bin/bash
## ====================================
## File Backup Utility
## ====================================
## --- Strict mode ---
set -euo pipefail
## --- Script metadata ---
SCRIPT_NAME="$(basename "$0")"
SCRIPT_VERSION="1.0.0"
## --- Default configuration ---
SOURCE_DIR=${SOURCE_DIR:-"$(pwd)"}
BACKUP_DIR=${BACKUP_DIR:-"/tmp/backups"}
BACKUP_NAME=${BACKUP_NAME:-"backup_$(date +%Y%m%d_%H%M%S)"}
EXCLUDE_PATTERN=${EXCLUDE_PATTERN:-"*.tmp"}
VERBOSE=${VERBOSE:-"false"}
## --- Helper functions ---
log() {
if [[ "$VERBOSE" == "true" ]]; then
echo "$(date "+%Y-%m-%d %H:%M:%S") - $1"
fi
}
error() {
echo "ERROR: $1" >&2
exit 1
}
usage() {
cat << EOF
Usage: $SCRIPT_NAME [options]
A simple file backup utility.
Options:
-s, --source DIR Source directory to backup (default: current directory)
-d, --destination DIR Backup destination directory (default: /tmp/backups)
-n, --name NAME Name for the backup archive (default: backup_YYYYMMDD_HHMMSS)
-e, --exclude PATTERN Files to exclude (default: *.tmp)
-v, --verbose Enable verbose output
-h, --help Show this help message and exit
Environment variables:
SOURCE_DIR Same as --source
BACKUP_DIR Same as --destination
BACKUP_NAME Same as --name
EXCLUDE_PATTERN Same as --exclude
VERBOSE Set to 'true' to enable verbose output
EOF
}
## --- Process command line arguments ---
while [[ $## -gt 0 ]]; do
case $1 in
-s | --source)
SOURCE_DIR="$2"
shift 2
;;
-d | --destination)
BACKUP_DIR="$2"
shift 2
;;
-n | --name)
BACKUP_NAME="$2"
shift 2
;;
-e | --exclude)
EXCLUDE_PATTERN="$2"
shift 2
;;
-v | --verbose)
VERBOSE="true"
shift
;;
-h | --help)
usage
exit 0
;;
*)
error "Unknown option: $1"
;;
esac
done
## --- Main function ---
main() {
## Validate source directory
if [[ ! -d "$SOURCE_DIR" ]]; then
error "Source directory does not exist: $SOURCE_DIR"
fi
## Create backup directory if it doesn't exist
if [[ ! -d "$BACKUP_DIR" ]]; then
log "Creating backup directory: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR" || error "Failed to create backup directory"
fi
## Full path for the backup file
BACKUP_FILE="$BACKUP_DIR/$BACKUP_NAME.tar.gz"
log "Starting backup from $SOURCE_DIR to $BACKUP_FILE"
log "Excluding files matching: $EXCLUDE_PATTERN"
## Create the backup
tar -czf "$BACKUP_FILE" \
--exclude="$EXCLUDE_PATTERN" \
-C "$(dirname "$SOURCE_DIR")" "$(basename "$SOURCE_DIR")" \
|| error "Backup failed"
## Check if backup was created
if [[ -f "$BACKUP_FILE" ]]; then
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo "Backup completed successfully: $BACKUP_FILE ($BACKUP_SIZE)"
else
error "Backup file was not created"
fi
}
## --- Run main function ---
main
- Torne o script executável:
chmod +x backup.sh
- Execute o script com as configurações padrão:
./backup.sh
Você deve ver uma mensagem confirmando que o backup foi criado com sucesso.
- Verifique o arquivo de backup:
ls -lh /tmp/backups/
- Tente executar o script com opções diferentes:
./backup.sh --source ~/project --destination ~/backups --name my_project_backup --verbose
Se o diretório ~/backups não existir, o script o criará. Você pode ver um erro se não tiver permissões de gravação para criar esse diretório.
Testando o Tratamento de Erros em Nosso Script de Backup
Vamos testar como nosso script lida com erros:
- Tente fazer backup de um diretório inexistente:
./backup.sh --source /path/that/does/not/exist
Você deve ver uma mensagem de erro como:
ERROR: Source directory does not exist: /path/that/does/not/exist
- Tente definir um destino de backup inválido (onde você não tem permissões de gravação):
./backup.sh --destination /root/backups
Você deve ver uma mensagem de erro indicando que o script falhou ao criar o diretório de backup.
Criando um Ambiente de Teste
Vamos criar um ambiente de teste para demonstrar nosso script de backup:
- Crie uma estrutura de diretório de teste:
mkdir -p ~/project/test_backup/{docs,images,code}
touch ~/project/test_backup/docs/{readme.md,manual.pdf}
touch ~/project/test_backup/images/{logo.png,banner.jpg}
touch ~/project/test_backup/code/{script.sh,data.tmp,config.json}
- Execute o script de backup neste diretório de teste:
./backup.sh --source ~/project/test_backup --exclude "*.tmp" --verbose
- Liste os arquivos no backup:
tar -tvf /tmp/backups/backup_*.tar.gz | sort
Você deve ver todos os arquivos, exceto aqueles que correspondem ao padrão de exclusão (*.tmp).
Este script de backup demonstra todos os conceitos que abordamos:
- Definir valores padrão para variáveis usando expansão de parâmetros
- Usar o modo estrito para detectar erros
- Lidar com argumentos de linha de comando e variáveis de ambiente
- Fornecer feedback ao usuário e mensagens de erro
- Validar entradas e lidar com casos extremos
Com essas técnicas, você pode escrever scripts Bash robustos que lidam com variáveis não definidas de forma elegante e proporcionam uma melhor experiência ao usuário.