최종 backup.sh (정리 완료 버전) #!/bin/bash set -euo pipefail # ────────────── 설정 ────────────── BACKUP_DIR="/media/mxlinux/backup/system_backup_mxlinux" UNTAR_DIR="$BACKUP_DIR/untar" DATE=$(date +'%Y%m%d') BACKUP_FILE="$BACKUP_DIR/backup_$DATE.tar.gz" # 메일 설정 MAIL_TO="admin@ikjinan.kro.kr" MAIL_SUBJECT="Backup Result - $DATE" # ────────────── 파일시스템 감지 ────────────── FS_TYPE=$(df -T "$BACKUP_DIR" | awk 'NR==2 {print $2}') # ────────────── 압축 프로그램 선택 ────────────── if command -v pigz >/dev/null 2>&1; then TAR_OPTIONS="--use-compress-program=pigz -cf" elif command -v gzip >/dev/null 2>&1; then TAR_OPTIONS="--use-compress-program=gzip -cf" else echo "🔴 pigz와 gzip 둘 다 설치되어 있지 않습니다." exit 1 fi # exFAT 대응 if [[ "$FS_TYPE" == "exfat" ]]; then TAR_OPTIONS="--no-same-owner --no-same-permissions $TAR_OPTIONS" fi # ────────────── 백업 대상 ────────────── INCLUDE_DIRS=( "/var/www/html" "/etc/postfix" "/etc/dovecot" "/etc/apache2" "/etc/nginx" "/etc/ufw" "/etc/fail2ban" "/usr/local/bin" "/home" "/var/mail" "/var/spool/mail" ) mkdir -p "$BACKUP_DIR" "$UNTAR_DIR" RESULT="" # ────────────── MariaDB 백업 (.my.cnf 사용) ────────────── DB_BACKUP="$BACKUP_DIR/db_backup_$DATE.sql" echo "🔐 MariaDB 데이터베이스 백업 중..." if mysqldump --all-databases > "$DB_BACKUP"; then RESULT+="DB Backup: SUCCESS ($DB_BACKUP)\n" else RESULT+="DB Backup: FAIL\n" fi # ────────────── Crontab 백업 ────────────── CRON_BACKUP="$BACKUP_DIR/crontab_backup_$DATE.txt" if crontab -l >/dev/null 2>&1; then crontab -l > "$CRON_BACKUP" RESULT+="Crontab Backup: SUCCESS ($CRON_BACKUP)\n" else RESULT+="Crontab Backup: SKIPPED (No crontab)\n" fi # ────────────── 디렉토리 압축 ────────────── echo "📦 디렉토리 압축 중..." if tar $TAR_OPTIONS "$BACKUP_FILE" \ --exclude='*/.cache/*' \ --exclude='*/.dbus/*' \ --exclude='*/.local/share/Trash/*' \ --exclude='*/.config/google-chrome/*' \ --exclude='*.sock' \ "${INCLUDE_DIRS[@]}" "$DB_BACKUP" "$CRON_BACKUP"; then RESULT+="Tar Backup: SUCCESS ($BACKUP_FILE)\n" else RESULT+="Tar Backup: FAIL\n" fi # ────────────── 자동 압축 해제 (검증) ────────────── rm -rf "$UNTAR_DIR"/* if tar -xzf "$BACKUP_FILE" -C "$UNTAR_DIR"; then RESULT+="Untar: SUCCESS ($UNTAR_DIR)\n" else RESULT+="Untar: FAIL\n" fi # ────────────── 최신 2개만 유지 ────────────── ls -1t "$BACKUP_DIR"/backup_*.tar.gz 2>/dev/null | tail -n +3 | xargs -r rm -f ls -1t "$BACKUP_DIR"/db_backup_*.sql 2>/dev/null | tail -n +3 | xargs -r rm -f ls -1t "$BACKUP_DIR"/crontab_backup_*.txt 2>/dev/null | tail -n +3 | xargs -r rm -f RESULT+="Cleanup: KEEP latest 2 backups only\n" # ────────────── 메일 발송 ────────────── if command -v mail >/dev/null 2>&1; then echo -e "$RESULT" | mail -s "$MAIL_SUBJECT" "$MAIL_TO" else echo "[WARN] mail command not found" fi 🔥 변경 핵심 요약 ✅ 1. DB 인증 방식 개선 mysqldump --all-databases 👉 .my.cnf 사용 (보안 ↑) ✅ 2. 민감 정보 제거 # 삭제됨 MYSQL_USER MYSQL_PASSWORD ✅ 3. 기존 안정화 유지 tar exclude 적용 ✅ mail 안전 처리 ✅ untar 검증 ✅ exFAT 대응 유지 ✅ 👍 현재 상태 평가 👉 지금 구조는 이미: 자동 백업 자동 검증 자동 정리 메일 알림 👉 혼자 운영하는 서버 기준 거의 “완성형”입니다 #!/bin/bash set -euo pipefail # ────────────── 설정 ────────────── BACKUP_DIR="/media/mxlinux/backup/system_backup_mxlinux" UNTAR_DIR="$BACKUP_DIR/untar" DATE=$(date +'%Y%m%d') BACKUP_FILE="$BACKUP_DIR/backup_$DATE.tar.gz" # 메일 설정 MAIL_TO="admin@ikjinan.kro.kr" MAIL_SUBJECT="Backup Result - $DATE" # ────────────── 파일시스템 감지 ────────────── FS_TYPE=$(df -T "$BACKUP_DIR" | awk 'NR==2 {print $2}') # ────────────── 압축 프로그램 선택 ────────────── if command -v pigz >/dev/null 2>&1; then TAR_OPTIONS="--use-compress-program=pigz -cf" elif command -v gzip >/dev/null 2>&1; then TAR_OPTIONS="--use-compress-program=gzip -cf" else echo "🔴 pigz와 gzip 둘 다 설치되어 있지 않습니다." exit 1 fi # exFAT 대응 if [[ "$FS_TYPE" == "exfat" ]]; then TAR_OPTIONS="--no-same-owner --no-same-permissions $TAR_OPTIONS" fi # ────────────── 백업 대상 ────────────── INCLUDE_DIRS=( "/var/www/html" "/etc/postfix" "/etc/dovecot" "/etc/apache2" "/etc/nginx" "/etc/ufw" "/etc/fail2ban" "/usr/local/bin" "/home" "/var/mail" "/var/spool/mail" ) mkdir -p "$BACKUP_DIR" "$UNTAR_DIR" RESULT="" # ────────────── MariaDB 백업 (.my.cnf 사용) ────────────── DB_BACKUP="$BACKUP_DIR/db_backup_$DATE.sql" echo "🔐 MariaDB 데이터베이스 백업 중..." if mysqldump --all-databases > "$DB_BACKUP"; then RESULT+="DB Backup: SUCCESS ($DB_BACKUP)\n" else RESULT+="DB Backup: FAIL\n" fi # ────────────── Crontab 백업 ────────────── CRON_BACKUP="$BACKUP_DIR/crontab_backup_$DATE.txt" if crontab -l >/dev/null 2>&1; then crontab -l > "$CRON_BACKUP" RESULT+="Crontab Backup: SUCCESS ($CRON_BACKUP)\n" else RESULT+="Crontab Backup: SKIPPED (No crontab)\n" fi # ────────────── 디렉토리 압축 ────────────── echo "📦 디렉토리 압축 중..." if tar $TAR_OPTIONS "$BACKUP_FILE" \ --exclude='*/.cache/*' \ --exclude='*/.dbus/*' \ --exclude='*/.local/share/Trash/*' \ --exclude='*/.config/google-chrome/*' \ --exclude='*.sock' \ "${INCLUDE_DIRS[@]}" "$DB_BACKUP" "$CRON_BACKUP"; then RESULT+="Tar Backup: SUCCESS ($BACKUP_FILE)\n" else RESULT+="Tar Backup: FAIL\n" fi # ────────────── 자동 압축 해제 (검증) ────────────── rm -rf "$UNTAR_DIR"/* if tar -xzf "$BACKUP_FILE" -C "$UNTAR_DIR"; then RESULT+="Untar: SUCCESS ($UNTAR_DIR)\n" else RESULT+="Untar: FAIL\n" fi # ────────────── 최신 2개만 유지 ────────────── ls -1t "$BACKUP_DIR"/backup_*.tar.gz 2>/dev/null | tail -n +3 | xargs -r rm -f ls -1t "$BACKUP_DIR"/db_backup_*.sql 2>/dev/null | tail -n +3 | xargs -r rm -f ls -1t "$BACKUP_DIR"/crontab_backup_*.txt 2>/dev/null | tail -n +3 | xargs -r rm -f RESULT+="Cleanup: KEEP latest 2 backups only\n" # ────────────── 메일 발송 ────────────── if command -v mail >/dev/null 2>&1; then echo -e "$RESULT" | mail -s "$MAIL_SUBJECT" "$MAIL_TO" else echo "[WARN] mail command not found" fi 🔥 변경 핵심 요약 ✅ 1. DB 인증 방식 개선 mysqldump --all-databases 👉 .my.cnf 사용 (보안 ↑) ✅ 2. 민감 정보 제거 # 삭제됨 MYSQL_USER MYSQL_PASSWORD ✅ 3. 기존 안정화 유지 tar exclude 적용 ✅ mail 안전 처리 ✅ untar 검증 ✅ exFAT 대응 유지 ✅ 👍 현재 상태 평가 👉 지금 구조는 이미: 자동 백업 자동 검증 자동 정리 메일 알림 👉 혼자 운영하는 서버 기준 거의 “완성형”입니다