|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +kill_pids() { |
| 4 | + app=$1 |
| 5 | + ids=$(ps aux | grep "${app}" | grep -v grep | awk '{print $2}') |
| 6 | + for id in ${ids}; do |
| 7 | + kill -9 "${id}" >/dev/null 2>&1 |
| 8 | + done |
| 9 | +} |
| 10 | + |
| 11 | +## Wait for the tunnel to finish connecting. |
| 12 | +wait_for_tunnel() { |
| 13 | + while : ; do |
| 14 | + [ -n "$(grep 'Press Control-C to stop.' backup.txt)" ] && break |
| 15 | + echo "Waiting for tunnel..." |
| 16 | + sleep 1 |
| 17 | + done |
| 18 | +} |
| 19 | + |
| 20 | +date |
| 21 | + |
| 22 | +## Create a tunnel through the application to pull the database. |
| 23 | +echo "Creating tunnel to database..." |
| 24 | +cf enable-ssh "${PROJECT}-drupal-${CF_SPACE}" |
| 25 | +cf restart --strategy rolling "${PROJECT}-drupal-${CF_SPACE}" |
| 26 | +cf connect-to-service --no-client "${PROJECT}-drupal-${CF_SPACE}" "${PROJECT}-mysql-${CF_SPACE}" > backup.txt & |
| 27 | + |
| 28 | +wait_for_tunnel |
| 29 | + |
| 30 | +date |
| 31 | + |
| 32 | +## Create variables and credential file for MySQL login. |
| 33 | +echo "Backing up 'prod' database..." |
| 34 | +{ |
| 35 | + host=$(cat backup.txt | grep -i host | awk '{print $2}') |
| 36 | + port=$(cat backup.txt | grep -i port | awk '{print $2}') |
| 37 | + username=$(cat backup.txt | grep -i username | awk '{print $2}') |
| 38 | + password=$(cat backup.txt | grep -i password | awk '{print $2}') |
| 39 | + dbname=$(cat backup.txt | grep -i '^name' | awk '{print $2}') |
| 40 | + |
| 41 | + mkdir ~/.mysql && chmod 0700 ~/.mysql |
| 42 | + |
| 43 | + echo "[mysqldump]" > ~/.mysql/mysqldump.cnf |
| 44 | + echo "user=${username}" >> ~/.mysql/mysqldump.cnf |
| 45 | + echo "password=${password}" >> ~/.mysql/mysqldump.cnf |
| 46 | + chmod 400 ~/.mysql/mysqldump.cnf |
| 47 | + |
| 48 | + ## Exclude tables without data |
| 49 | + declare -a excluded_tables=( |
| 50 | + "cache_advagg_minify" |
| 51 | + "cache_bootstrap" |
| 52 | + "cache_config" |
| 53 | + "cache_container" |
| 54 | + "cache_data" |
| 55 | + "cache_default" |
| 56 | + "cache_discovery" |
| 57 | + "cache_discovery_migration" |
| 58 | + "cache_dynamic_page_cache" |
| 59 | + "cache_entity" |
| 60 | + "cache_menu" |
| 61 | + "cache_migrate" |
| 62 | + "cache_page" |
| 63 | + "cache_render" |
| 64 | + "cache_rest" |
| 65 | + "cache_toolbar" |
| 66 | + "sessions" |
| 67 | + "watchdog" |
| 68 | + "webprofiler" |
| 69 | + ) |
| 70 | + |
| 71 | + ignored_tables_string='' |
| 72 | + for table in "${excluded_tables[@]}" |
| 73 | + do |
| 74 | + ignored_tables_string+=" --ignore-table=${dbname}.${table}" |
| 75 | + done |
| 76 | + |
| 77 | + ## Dump structure |
| 78 | + mysqldump \ |
| 79 | + --defaults-extra-file=~/.mysql/mysqldump.cnf \ |
| 80 | + --host="${host}" \ |
| 81 | + --port="${port}" \ |
| 82 | + --protocol=TCP \ |
| 83 | + --no-data \ |
| 84 | + "${dbname}" > "backup_${CF_SPACE}.sql" |
| 85 | + |
| 86 | + ## Dump content |
| 87 | + mysqldump \ |
| 88 | + --defaults-extra-file=~/.mysql/mysqldump.cnf \ |
| 89 | + --host="${host}" \ |
| 90 | + --port="${port}" \ |
| 91 | + --protocol=TCP \ |
| 92 | + --no-create-info \ |
| 93 | + --skip-triggers \ |
| 94 | + "${ignored_tables_string}" \ |
| 95 | + "${dbname}" >> "backup_${CF_SPACE}.sql" |
| 96 | + |
| 97 | + ## Patch out any MySQL 'SET' commands that require admin. |
| 98 | + sed -i 's/^SET /-- &/' "backup_${CF_SPACE}.sql" |
| 99 | + |
| 100 | +} >/dev/null 2>&1 |
| 101 | + |
| 102 | +date |
| 103 | + |
| 104 | +## Kill the backgrounded SSH tunnel. |
| 105 | +echo "Cleaning up old connections..." |
| 106 | +{ |
| 107 | + kill_pids "connect-to-service" |
| 108 | +} >/dev/null 2>&1 |
| 109 | + |
| 110 | +## Disable ssh. |
| 111 | +echo "Disabling ssh..." |
| 112 | +cf disable-ssh "${PROJECT}-drupal-${CF_SPACE}" |
| 113 | + |
| 114 | +rm -rf backup.txt ~/.mysql |
| 115 | + |
| 116 | +echo "Saving to backup bucket..." |
| 117 | +{ |
| 118 | + cf target -s "${PROJECT}-${CF_SPACE}" >/dev/null 2>&1 |
| 119 | + |
| 120 | + export service="${PROJECT}-backup" |
| 121 | + export service_key="${service}-key" |
| 122 | + cf delete-service-key "${service}" "${service_key}" -f >/dev/null 2>&1 |
| 123 | + cf create-service-key "${service}" "${service_key}" >/dev/null 2>&1 |
| 124 | + sleep 2 |
| 125 | + |
| 126 | + s3_credentials=$(cf service-key "${service}" "${service_key}" | tail -n +2) |
| 127 | + export s3_credentials |
| 128 | + |
| 129 | + AWS_ACCESS_KEY_ID=$(echo "${s3_credentials}" | jq -r '.credentials.access_key_id') |
| 130 | + export AWS_ACCESS_KEY_ID |
| 131 | + |
| 132 | + bucket=$(echo "${s3_credentials}" | jq -r '.credentials.bucket') |
| 133 | + export bucket |
| 134 | + |
| 135 | + AWS_DEFAULT_REGION=$(echo "${s3_credentials}" | jq -r '.credentials.region') |
| 136 | + export AWS_DEFAULT_REGION |
| 137 | + |
| 138 | + AWS_SECRET_ACCESS_KEY=$(echo "${s3_credentials}" | jq -r '.credentials.secret_access_key') |
| 139 | + export AWS_SECRET_ACCESS_KEY |
| 140 | + |
| 141 | + # copy latest database to top level |
| 142 | + gzip "backup_${CF_SPACE}.sql" |
| 143 | + aws s3 cp "./backup_${CF_SPACE}.sql.gz" "s3://${bucket}/${CF_SPACE}/latest.sql.gz" --no-verify-ssl >/dev/null 2>&1 && echo "Successfully copied latest.sql.gz to S3!" || echo "Failed to copy latest.sql.gz to S3!" |
| 144 | + |
| 145 | + cf delete-service-key "${service}" "${service_key}" -f >/dev/null 2>&1 |
| 146 | +} |
| 147 | + |
| 148 | +date |
0 commit comments