Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

migration.sh 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #!/bin/bash
  2. # RAGFlow Data Migration Script
  3. # Usage: ./migration.sh [backup|restore] [backup_folder]
  4. #
  5. # This script helps you backup and restore RAGFlow Docker volumes
  6. # including MySQL, MinIO, Redis, and Elasticsearch data.
  7. set -e # Exit on any error
  8. # Instead, we'll handle errors manually for better debugging experience
  9. # Default values
  10. DEFAULT_BACKUP_FOLDER="backup"
  11. VOLUMES=("docker_mysql_data" "docker_minio_data" "docker_redis_data" "docker_esdata01")
  12. BACKUP_FILES=("mysql_backup.tar.gz" "minio_backup.tar.gz" "redis_backup.tar.gz" "es_backup.tar.gz")
  13. # Function to display help information
  14. show_help() {
  15. echo "RAGFlow Data Migration Tool"
  16. echo ""
  17. echo "USAGE:"
  18. echo " $0 <operation> [backup_folder]"
  19. echo ""
  20. echo "OPERATIONS:"
  21. echo " backup - Create backup of all RAGFlow data volumes"
  22. echo " restore - Restore RAGFlow data volumes from backup"
  23. echo " help - Show this help message"
  24. echo ""
  25. echo "PARAMETERS:"
  26. echo " backup_folder - Name of backup folder (default: '$DEFAULT_BACKUP_FOLDER')"
  27. echo ""
  28. echo "EXAMPLES:"
  29. echo " $0 backup # Backup to './backup' folder"
  30. echo " $0 backup my_backup # Backup to './my_backup' folder"
  31. echo " $0 restore # Restore from './backup' folder"
  32. echo " $0 restore my_backup # Restore from './my_backup' folder"
  33. echo ""
  34. echo "DOCKER VOLUMES:"
  35. echo " - docker_mysql_data (MySQL database)"
  36. echo " - docker_minio_data (MinIO object storage)"
  37. echo " - docker_redis_data (Redis cache)"
  38. echo " - docker_esdata01 (Elasticsearch indices)"
  39. }
  40. # Function to check if Docker is running
  41. check_docker() {
  42. if ! docker info >/dev/null 2>&1; then
  43. echo "❌ Error: Docker is not running or not accessible"
  44. echo "Please start Docker and try again"
  45. exit 1
  46. fi
  47. }
  48. # Function to check if volume exists
  49. volume_exists() {
  50. local volume_name=$1
  51. docker volume inspect "$volume_name" >/dev/null 2>&1
  52. }
  53. # Function to check if any containers are using the target volumes
  54. check_containers_using_volumes() {
  55. echo "🔍 Checking for running containers that might be using target volumes..."
  56. # Get all running containers
  57. local running_containers=$(docker ps --format "{{.Names}}")
  58. if [ -z "$running_containers" ]; then
  59. echo "✅ No running containers found"
  60. return 0
  61. fi
  62. # Check each running container for volume usage
  63. local containers_using_volumes=()
  64. local volume_usage_details=()
  65. for container in $running_containers; do
  66. # Get container's mount information
  67. local mounts=$(docker inspect "$container" --format '{{range .Mounts}}{{.Source}}{{"|"}}{{end}}' 2>/dev/null || echo "")
  68. # Check if any of our target volumes are used by this container
  69. for volume in "${VOLUMES[@]}"; do
  70. if echo "$mounts" | grep -q "$volume"; then
  71. containers_using_volumes+=("$container")
  72. volume_usage_details+=("$container -> $volume")
  73. break
  74. fi
  75. done
  76. done
  77. # If any containers are using our volumes, show error and exit
  78. if [ ${#containers_using_volumes[@]} -gt 0 ]; then
  79. echo ""
  80. echo "❌ ERROR: Found running containers using target volumes!"
  81. echo ""
  82. echo "📋 Running containers status:"
  83. docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
  84. echo ""
  85. echo "🔗 Volume usage details:"
  86. for detail in "${volume_usage_details[@]}"; do
  87. echo " - $detail"
  88. done
  89. echo ""
  90. echo "🛑 SOLUTION: Stop the containers before performing backup/restore operations:"
  91. echo " docker-compose -f docker/<your-docker-compose-file>.yml down"
  92. echo ""
  93. echo "💡 After backup/restore, you can restart with:"
  94. echo " docker-compose -f docker/<your-docker-compose-file>.yml up -d"
  95. echo ""
  96. exit 1
  97. fi
  98. echo "✅ No containers are using target volumes, safe to proceed"
  99. return 0
  100. }
  101. # Function to confirm user action
  102. confirm_action() {
  103. local message=$1
  104. echo -n "$message (y/N): "
  105. read -r response
  106. case "$response" in
  107. [yY]|[yY][eE][sS]) return 0 ;;
  108. *) return 1 ;;
  109. esac
  110. }
  111. # Function to perform backup
  112. perform_backup() {
  113. local backup_folder=$1
  114. echo "🚀 Starting RAGFlow data backup..."
  115. echo "📁 Backup folder: $backup_folder"
  116. echo ""
  117. # Check if any containers are using the volumes
  118. check_containers_using_volumes
  119. # Create backup folder if it doesn't exist
  120. mkdir -p "$backup_folder"
  121. # Backup each volume
  122. for i in "${!VOLUMES[@]}"; do
  123. local volume="${VOLUMES[$i]}"
  124. local backup_file="${BACKUP_FILES[$i]}"
  125. local step=$((i + 1))
  126. echo "📦 Step $step/4: Backing up $volume..."
  127. if volume_exists "$volume"; then
  128. docker run --rm \
  129. -v "$volume":/source \
  130. -v "$(pwd)/$backup_folder":/backup \
  131. alpine tar czf "/backup/$backup_file" -C /source .
  132. echo "✅ Successfully backed up $volume to $backup_folder/$backup_file"
  133. else
  134. echo "⚠️ Warning: Volume $volume does not exist, skipping..."
  135. fi
  136. echo ""
  137. done
  138. echo "🎉 Backup completed successfully!"
  139. echo "📍 Backup location: $(pwd)/$backup_folder"
  140. # List backup files with sizes
  141. echo ""
  142. echo "📋 Backup files created:"
  143. for backup_file in "${BACKUP_FILES[@]}"; do
  144. if [ -f "$backup_folder/$backup_file" ]; then
  145. local size=$(ls -lh "$backup_folder/$backup_file" | awk '{print $5}')
  146. echo " - $backup_file ($size)"
  147. fi
  148. done
  149. }
  150. # Function to perform restore
  151. perform_restore() {
  152. local backup_folder=$1
  153. echo "🔄 Starting RAGFlow data restore..."
  154. echo "📁 Backup folder: $backup_folder"
  155. echo ""
  156. # Check if any containers are using the volumes
  157. check_containers_using_volumes
  158. # Check if backup folder exists
  159. if [ ! -d "$backup_folder" ]; then
  160. echo "❌ Error: Backup folder '$backup_folder' does not exist"
  161. exit 1
  162. fi
  163. # Check if all backup files exist
  164. local missing_files=()
  165. for backup_file in "${BACKUP_FILES[@]}"; do
  166. if [ ! -f "$backup_folder/$backup_file" ]; then
  167. missing_files+=("$backup_file")
  168. fi
  169. done
  170. if [ ${#missing_files[@]} -gt 0 ]; then
  171. echo "❌ Error: Missing backup files:"
  172. for file in "${missing_files[@]}"; do
  173. echo " - $file"
  174. done
  175. echo "Please ensure all backup files are present in '$backup_folder'"
  176. exit 1
  177. fi
  178. # Check for existing volumes and warn user
  179. local existing_volumes=()
  180. for volume in "${VOLUMES[@]}"; do
  181. if volume_exists "$volume"; then
  182. existing_volumes+=("$volume")
  183. fi
  184. done
  185. if [ ${#existing_volumes[@]} -gt 0 ]; then
  186. echo "⚠️ WARNING: The following Docker volumes already exist:"
  187. for volume in "${existing_volumes[@]}"; do
  188. echo " - $volume"
  189. done
  190. echo ""
  191. echo "🔴 IMPORTANT: Restoring will OVERWRITE existing data!"
  192. echo "💡 Recommendation: Create a backup of your current data first:"
  193. echo " $0 backup current_backup_$(date +%Y%m%d_%H%M%S)"
  194. echo ""
  195. if ! confirm_action "Do you want to continue with the restore operation?"; then
  196. echo "❌ Restore operation cancelled by user"
  197. exit 0
  198. fi
  199. fi
  200. # Create volumes and restore data
  201. for i in "${!VOLUMES[@]}"; do
  202. local volume="${VOLUMES[$i]}"
  203. local backup_file="${BACKUP_FILES[$i]}"
  204. local step=$((i + 1))
  205. echo "🔧 Step $step/4: Restoring $volume..."
  206. # Create volume if it doesn't exist
  207. if ! volume_exists "$volume"; then
  208. echo " 📋 Creating Docker volume: $volume"
  209. docker volume create "$volume"
  210. else
  211. echo " 📋 Using existing Docker volume: $volume"
  212. fi
  213. # Restore data
  214. echo " 📥 Restoring data from $backup_file..."
  215. docker run --rm \
  216. -v "$volume":/target \
  217. -v "$(pwd)/$backup_folder":/backup \
  218. alpine tar xzf "/backup/$backup_file" -C /target
  219. echo "✅ Successfully restored $volume"
  220. echo ""
  221. done
  222. echo "🎉 Restore completed successfully!"
  223. echo "💡 You can now start your RAGFlow services"
  224. }
  225. # Main script logic
  226. main() {
  227. # Check if Docker is available
  228. check_docker
  229. # Parse command line arguments
  230. local operation=${1:-}
  231. local backup_folder=${2:-$DEFAULT_BACKUP_FOLDER}
  232. # Handle help or no arguments
  233. if [ -z "$operation" ] || [ "$operation" = "help" ] || [ "$operation" = "-h" ] || [ "$operation" = "--help" ]; then
  234. show_help
  235. exit 0
  236. fi
  237. # Validate operation
  238. case "$operation" in
  239. backup)
  240. perform_backup "$backup_folder"
  241. ;;
  242. restore)
  243. perform_restore "$backup_folder"
  244. ;;
  245. *)
  246. echo "❌ Error: Invalid operation '$operation'"
  247. echo ""
  248. show_help
  249. exit 1
  250. ;;
  251. esac
  252. }
  253. # Run main function with all arguments
  254. main "$@"