diff --git a/DVDBR.sh b/DVDBR.sh new file mode 100644 index 0000000..101fffd --- /dev/null +++ b/DVDBR.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +# Define timestamp for logs and backup filenames +TIMESTAMP=$(date +"%Y%m%d_%H%M_%3N") +LOGFILE="DVDBR_${TIMESTAMP}.log" + +# Function to log messages +log() { + echo "[$(date +"%Y-%m-%d %H:%M:%S.%3N")] $1" | tee -a "$LOGFILE" +} + +# Check if the user is in the docker group or requires sudo +if ! groups | grep -q '\bdocker\b'; then + log "User is not in the docker group, requesting sudo access." + sudo -v || { log "Failed to obtain sudo access."; exit 1; } + SUDO_CMD="sudo" +else + SUDO_CMD="" +fi + +# List available Docker volumes +VOLUMES=$($SUDO_CMD docker volume ls --format "{{.Name}}") +if [[ -z "$VOLUMES" ]]; then + log "No Docker volumes found. Exiting." + exit 1 +fi + +# Ask which volumes to backup +log "Available Docker volumes:" +echo "$VOLUMES" +read -p "Enter the volume(s) to backup (space-separated): " SELECTED_VOLUMES + +# Ask if timestamp should be included in the backup file name +read -p "Include timestamp in backup filename? [y/N]: " INCLUDE_TIMESTAMP + +# Find running containers using selected volumes +declare -A CONTAINER_MAP +for VOLUME in $SELECTED_VOLUMES; do + while read -r CONTAINER_ID; do + if [[ -n "$CONTAINER_ID" ]]; then + CONTAINER_NAME=$($SUDO_CMD docker ps --filter "id=$CONTAINER_ID" --format "{{.Names}}") + CONTAINER_MAP["$CONTAINER_ID"]="$CONTAINER_NAME ($CONTAINER_ID)" + fi + done < <($SUDO_CMD docker ps --format "{{.ID}}" --filter "volume=$VOLUME") +done + +# Display affected containers +if [[ "${#CONTAINER_MAP[@]}" -gt 0 ]]; then + log "The following containers use the selected volumes and may be impacted: ${CONTAINER_MAP[*]}" +fi + +# Ask if containers should be stopped before backup +read -p "Do you want to stop them before backup? (recommended) [y/N]: " STOP_CONTAINERS + +# Ask for backup method +read -p "Save locally? [y/N]: " SAVE_LOCAL +read -p "Save to remote server via SSH? [y/N]: " SAVE_REMOTE + +# Ask for local backup path if needed +if [[ "$SAVE_LOCAL" =~ ^[Yy]$ ]]; then + read -p "Enter local backup directory (default: current directory): " LOCAL_PATH + LOCAL_PATH=${LOCAL_PATH:-$(pwd)} + mkdir -p "$LOCAL_PATH" +fi + +# Ask for SSH details if remote backup is selected +if [[ "$SAVE_REMOTE" =~ ^[Yy]$ ]]; then + read -p "Enter SSH private key path (default: ~/.ssh/id_rsa): " SSH_KEY + SSH_KEY=${SSH_KEY:-~/.ssh/id_rsa} + read -p "Enter SSH user: " SSH_USER + read -p "Enter SSH server hostname/IP: " SSH_HOST + read -p "Enter remote backup directory (default: ~/BACKUP): " REMOTE_PATH + REMOTE_PATH=${REMOTE_PATH:-~/BACKUP} +fi + +# Ask if containers should be restarted after backup (only if they were stopped) +if [[ "$STOP_CONTAINERS" =~ ^[Yy]$ ]]; then + read -p "Restart stopped containers after backup? [y/N]: " RESTART_CONTAINERS +fi + +# Summary before execution +echo -e "\nSummary of actions:" +echo "- Selected volumes: $SELECTED_VOLUMES" +echo "- Containers that may be using these volumes: ${CONTAINER_MAP[*]}" +echo "- Stop containers before backup: ${STOP_CONTAINERS}"; +echo "- Restart stopped containers after backup: ${RESTART_CONTAINERS}"; +echo "- Save locally: ${SAVE_LOCAL}"; [[ "$SAVE_LOCAL" =~ ^[Yy]$ ]] && echo " -> Path: $LOCAL_PATH" +echo "- Save remotely: ${SAVE_REMOTE}"; [[ "$SAVE_REMOTE" =~ ^[Yy]$ ]] && echo " -> SSH: $SSH_USER@$SSH_HOST:$REMOTE_PATH" +read -p "Proceed with backup? [y/N]: " CONFIRM +[[ "$CONFIRM" =~ ^[Yy]$ ]] || { log "Backup cancelled."; exit 0; } + +# Stop containers if confirmed +if [[ "$STOP_CONTAINERS" =~ ^[Yy]$ ]]; then + for CONTAINER_ID in "${!CONTAINER_MAP[@]}"; do + log "Stopping container: ${CONTAINER_MAP[$CONTAINER_ID]}" + $SUDO_CMD docker stop "$CONTAINER_ID" + done +fi + +# Perform backup +for VOLUME in $SELECTED_VOLUMES; do + BACKUP_FILE="$VOLUME.tar.gz" + [[ "$INCLUDE_TIMESTAMP" =~ ^[Yy]$ ]] && BACKUP_FILE="${VOLUME}_${TIMESTAMP}.tar.gz" + + log "Streaming $VOLUME backup directly to remote server via ssh cat" + if ! $SUDO_CMD docker run --rm -v $VOLUME:/data:ro alpine sh -c "tar czf - -C /data ." | ssh -i "$SSH_KEY" "$SSH_USER@$SSH_HOST" "cat > $REMOTE_PATH/$BACKUP_FILE"; then + log "⚠️ ssh cat failed, trying rsync..." + if ! rsync -avz -e "ssh -i $SSH_KEY" "$LOCAL_PATH/$BACKUP_FILE" "$SSH_USER@$SSH_HOST:$REMOTE_PATH/"; then + log "⚠️ rsync failed, trying SCP..." + scp -i "$SSH_KEY" "$LOCAL_PATH/$BACKUP_FILE" "$SSH_USER@$SSH_HOST:$REMOTE_PATH/" + fi + fi + +done + +# Restart stopped containers if requested +if [[ "$STOP_CONTAINERS" =~ ^[Yy]$ && "$RESTART_CONTAINERS" =~ ^[Yy]$ ]]; then + for CONTAINER_ID in "${!CONTAINER_MAP[@]}"; do + log "Restarting container: ${CONTAINER_MAP[$CONTAINER_ID]}" + $SUDO_CMD docker start "$CONTAINER_ID" + done +fi + +log "Backup process completed successfully."