#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' # ══════════════════════════════════════════════════════════════ # backup_automatico.sh — Backup automatizado do servidor # ══════════════════════════════════════════════════════════════ # ── Carrega .env se existir ────────────────────────────────── SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" [ -f "$SCRIPT_DIR/.env" ] && set -a && source "$SCRIPT_DIR/.env" && set +a # ── Configuração ───────────────────────────────────────────── MYSQL_USER="${MYSQL_USER:-root}" MYSQL_PASS="${MYSQL_PASS:-}" MYSQLDUMP="/usr/bin/mysqldump" SFTP_HOST="${SFTP_HOST:-}" SFTP_USER="${SFTP_USER:-}" SFTP_DIR="${SFTP_DIR:-}" DIRS_TO_BACKUP=( "/var/www" "/etc/nginx/sites-available" "/opt" ) LOG_FILE="/var/log/backup_server.log" LOCAL_RETENTION="${LOCAL_RETENTION:-3}" # ── Validações ─────────────────────────────────────────────── if [[ $EUID -ne 0 ]]; then echo "ERRO: execute como root (sudo)." >&2 exit 1 fi if [ -z "$MYSQL_PASS" ]; then echo "ERRO: MYSQL_PASS nao definida. Defina no arquivo .env." >&2 exit 1 fi if [ -z "$SFTP_HOST" ] || [ -z "$SFTP_USER" ] || [ -z "$SFTP_DIR" ]; then echo "ERRO: SFTP_HOST, SFTP_USER e SFTP_DIR devem estar definidas no .env." >&2 exit 1 fi if [ ! -x "$MYSQLDUMP" ]; then echo "ERRO: mysqldump nao encontrado. Instale: apt-get install mariadb-client" >&2 exit 1 fi # ── Log (fallback para /tmp) ───────────────────────────────── mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || LOG_FILE="/tmp/backup_server.log" touch "$LOG_FILE" 2>/dev/null || { LOG_FILE="/tmp/backup_server.log"; touch "$LOG_FILE"; } log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"; } # ── Timestamp e dirs temporarios ───────────────────────────── TIMESTAMP=$(date +"%Y%m%d_%H%M%S") BACKUP_NAME="backup_server217_${TIMESTAMP}" TMP_DIR="/tmp/${BACKUP_NAME}" ARCHIVE="/tmp/${BACKUP_NAME}.tar.gz" cleanup() { rm -rf "$TMP_DIR"; } trap cleanup EXIT # ── Espaco em disco ────────────────────────────────────────── AVAILABLE_MB=$(df --output=avail /tmp | tail -n1) [ "$AVAILABLE_MB" -lt 2048 ] && { echo "ERRO: espaco insuficiente (${AVAILABLE_MB}MB)." >&2; exit 1; } log "Iniciando backup: $BACKUP_NAME" # ── PASSO 1 — Bancos de dados ──────────────────────────────── log "PASSO 1 — Dump dos bancos MariaDB..." MYSQL_CNF="/tmp/.${BACKUP_NAME}_my.cnf" cat > "$MYSQL_CNF" </dev/null \ | grep -Ev "Database|information_schema|performance_schema|sys") DB_COUNT=0 for DB in $DATABASES; do "$MYSQLDUMP" --defaults-extra-file="$MYSQL_CNF" --single-transaction --routines --triggers --events \ "$DB" > "${TMP_DIR}/databases/${DB}.sql" 2>/dev/null && { log " OK: banco '$DB'" DB_COUNT=$((DB_COUNT + 1)) } || { log " ERRO: falha no dump de '$DB'" } done log " Total de bancos exportados: $DB_COUNT" rm -f "$MYSQL_CNF" # ── PASSO 2 — Diretorios ───────────────────────────────────── log "PASSO 2 — Copiando diretorios..." for DIR in "${DIRS_TO_BACKUP[@]}"; do [ -d "$DIR" ] || { log " PULANDO (nao existe): $DIR"; continue; } cp -a "$DIR" "${TMP_DIR}/" 2>/dev/null || log " ERRO: falha ao copiar '$DIR'" done # ── PASSO 3 — Compactacao ──────────────────────────────────── log "PASSO 3 — Compactando em .tar.gz..." tar czpf "$ARCHIVE" -C "$TMP_DIR" . 2>/dev/null || { log "ERRO: falha ao compactar." exit 1 } SIZE=$(du -h "$ARCHIVE" | cut -f1) log " Arquivo criado: ${BACKUP_NAME}.tar.gz (${SIZE})" # ── PASSO 4 — Envio SFTP ───────────────────────────────────── log "PASSO 4 — Enviando para ${SFTP_HOST}..." REMOTE_PATH="${SFTP_DIR}/${BACKUP_NAME}.tar.gz" SSH_OPTS=(-o ConnectTimeout=30 -o StrictHostKeyChecking=accept-new) ssh "${SSH_OPTS[@]}" "${SFTP_USER}@${SFTP_HOST}" "mkdir -p '${SFTP_DIR}' && chmod 755 '${SFTP_DIR}'" 2>/dev/null || { log "ERRO: falha ao criar pasta remota ${SFTP_DIR}." exit 1 } sftp "${SSH_OPTS[@]}" -b - "${SFTP_USER}@${SFTP_HOST}" <<< "put $ARCHIVE $REMOTE_PATH" > /dev/null 2>&1 || { log "ERRO: falha no envio SFTP." exit 1 } log " Enviado com sucesso para: sftp://${SFTP_USER}@${SFTP_HOST}${REMOTE_PATH}" # ── PASSO 5 — Limpeza local ────────────────────────────────── rm -f "$ARCHIVE" log " Arquivo local removido." if [ "$LOCAL_RETENTION" -gt 0 ]; then cd /tmp ls -1t backup_server217_*.tar.gz 2>/dev/null | tail -n +$((LOCAL_RETENTION + 1)) | while read -r f; do log " Removendo backup antigo: $f" rm -f "$f" done fi log "Backup finalizado com sucesso."