Guest User

Untitled

a guest
Jan 19th, 2019
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.72 KB | None | 0 0
  1. #!/usr/bin/env bash
  2.  
  3. # Original Author: Zhang Huangbin (zhb@iredmail.org)
  4. # Date: 16/09/2007
  5. # Purpose: Backup specified mysql databases with command 'mysqldump'.
  6. # License: This shell script is part of iRedMail project, released under
  7. # GPL v2.
  8. #
  9. # Modified By: Ioannis Angelakopoulos <ioagel@gmail.com>
  10. # Date: 18/01/2019
  11.  
  12. ###########################
  13. # REQUIREMENTS
  14. ###########################
  15. #
  16. # * Required commands:
  17. # + mysqldump
  18. # + mysql
  19. # + bzip2 or gzip # If bzip2 is not available, change 'CMD_COMPRESS'
  20. # # to use 'gzip'.
  21. #
  22.  
  23. ###########################
  24. # USAGE
  25. ###########################
  26. # * Set correct values for below variables:
  27. #
  28. # MYSQL_PASSWD[_FILE] REQUIRED
  29. # BACKUP_ROOTDIR default=/backup
  30. # MYSQL_HOST default=localhost
  31. # MYSQL_PORT default=3306
  32. # MYSQL_PROTO default=TCP
  33. # MYSQL_USER default=root
  34. # MYSQL_SINGLE_TX default=TRUE
  35. # DATABASES default=all
  36. # DB_CHARACTER_SET default=utf8
  37. # COMPRESS default=YES
  38. # CMD_COMPRESS default=bzip2 -9
  39. # DELETE_PLAIN_SQL_FILE default=YES
  40. # RUN_FREQ default=ONCE
  41. # SLEEP default=3600 -> 1 hour
  42. #
  43. #
  44. # Backup script suitable to run as a command in a mysql docker container
  45. # to backup databases running in production mysql containers or services.
  46. # It is optimized for docker thats why ENV vars are preferred
  47. # instead of commandline args.
  48. #
  49. # Create a dockerfile with a mysql base image and copy this script and use it as the COMMAND, then build and run:
  50. # Better use: floulab/mysql-backup from dockerhub.
  51. #
  52. # run once and exit
  53. # $ docker run --rm --link mysql-prod -e MYSQL_PASSWD=password -e MYSQL_HOST=mysql-prod floulab/mysql-backup
  54. #
  55. # run as a daemon and backup every 1 hour
  56. # $ docker run -d --link mysql-prod -e MYSQL_PASSWD=password -e MYSQL_HOST=mysql-prod -e RUN_FREQ=NONSTOP -v db_backups:/backup floulab/mysql-backup
  57. #
  58. # SUPPORTS Docker Secrets with MYSQL_PASSWD_FILE environment variable!
  59. #
  60. # run as a standalone script
  61. # $ MYSQL_PASSWD=password MYSQL_HOST=mysql.example.org bash mysql_backup.sh
  62. #
  63. #########################################################
  64. # Modify below variables to fit your need ----
  65. #########################################################
  66. # Where to store backup copies.
  67. BACKUP_ROOTDIR=${BACKUP_ROOTDIR:-/backup} # for docker, mount a volume here
  68.  
  69. MYSQL_HOST=${MYSQL_HOST:-localhost}
  70. MYSQL_PORT=${MYSQL_PORT:-3306}
  71. MYSQL_PROTO=${MYSQL_PROTO:-TCP} # either TCP or SOCKET
  72. MYSQL_USER=${MYSQL_USER:-root}
  73. MYSQL_SINGLE_TX=${MYSQL_SINGLE_TX:-TRUE} # either TRUE or FALSE, --single-transaction option
  74.  
  75. # Databases we should backup.
  76. # Multiple databases MUST be seperated by SPACE.
  77. # Your iRedMail server might have below databases:
  78. # mysql, roundcubemail, policyd (or postfixpolicyd), amavisd, iredadmin
  79. DATABASES=${DATABASES:---all-databases}
  80.  
  81. # Database character set for ALL databases.
  82. # Note: Currently, it doesn't support to specify character set for each databases.
  83. DB_CHARACTER_SET=${DB_CHARACTER_SET:-utf8}
  84.  
  85. # Compress plain SQL file: YES, NO.
  86. COMPRESS=${COMPRESS:-YES}
  87.  
  88. # Compression program: bzip2, gzip
  89. CMD_COMPRESS=${CMD_COMPRESS:-bzip2 -9}
  90.  
  91. # Delete plain SQL files after compressed. Compressed copy will be remained.
  92. DELETE_PLAIN_SQL_FILE=${DELETE_PLAIN_SQL_FILE:-YES}
  93.  
  94. # Run once or infinite loop: ONCE, NONSTOP
  95. RUN_FREQ=${RUN_FREQ:-ONCE}
  96.  
  97. # if NONSTOP use sleep for infinite loop: time in seconds
  98. SLEEP=${SLEEP:-3600}
  99.  
  100. #########################################################
  101. # You do *NOT* need to modify below lines.
  102. #########################################################
  103. # handle docker stop signal properly
  104. cleanup() {
  105. echo "Shuting down ..."
  106. kill -s SIGTERM $!
  107. exit 0
  108. }
  109. trap cleanup SIGINT SIGTERM
  110.  
  111. # thanks to mysql official image for the following func
  112. # usage: file_env VAR [DEFAULT]
  113. # ie: file_env 'XYZ_DB_PASSWORD' 'example'
  114. # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
  115. # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
  116. file_env() {
  117. local var="$1"
  118. local fileVar="${var}_FILE"
  119. local def="${2:-}"
  120. if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
  121. echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
  122. exit 1
  123. fi
  124. local val="$def"
  125. if [ "${!var:-}" ]; then
  126. val="${!var}"
  127. elif [ "${!fileVar:-}" ]; then
  128. val="$(< "${!fileVar}")"
  129. fi
  130. export "$var"="$val"
  131. unset "$fileVar"
  132. }
  133.  
  134. PATH='/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin'
  135.  
  136. # Commands.
  137. CMD_DATE='/bin/date'
  138. CMD_DU='du -sh'
  139. CMD_MYSQLDUMP='mysqldump'
  140. CMD_MYSQL='mysql'
  141.  
  142. # Verify compress program is either bzip2 or gzip
  143. if [[ ! "$CMD_COMPRESS" =~ ^bzip2.*|^gzip.* ]]; then
  144. echo "[ERROR] Compression ENV CMD_COMPRESS can either be 'bzip2' or 'gzip'." 1>&2
  145. exit 255
  146. fi
  147.  
  148. # Verify MYSQL_HOST is set
  149. if [ -z "$MYSQL_HOST" ]; then
  150. echo "[ERROR] MySQL Host ENV variable MYSQL_HOST is required." 1>&2
  151.  
  152. exit 255
  153. fi
  154.  
  155. file_env 'MYSQL_PASSWD'
  156. # Verify MYSQL_HOST is set
  157. if [ -z "$MYSQL_PASSWD" ]; then
  158. echo "[ERROR] MySQL Password ENV variable MYSQL_PASSWD is required." 1>&2
  159.  
  160. exit 255
  161. fi
  162.  
  163. # Verify MySQL connection.
  164. ${CMD_MYSQL} -u "$MYSQL_USER" --password="$MYSQL_PASSWD" --host="$MYSQL_HOST" --port="$MYSQL_PORT" --protocol="$MYSQL_PROTO" -e "show databases" &>/dev/null
  165. if [ X"$?" != X"0" ]; then
  166. echo "[ERROR] MySQL username or password or host or protocol is incorrect in file ${0}." 1>&2
  167. echo "Please fix them first." 1>&2
  168.  
  169. exit 255
  170. fi
  171.  
  172. backup_db()
  173. {
  174. # USAGE:
  175. # # backup dbname
  176. db="${1}"
  177.  
  178. if [ "$db" = "--all-databases" ]; then
  179. output_sql="${BACKUP_DIR}/all-${TIMESTAMP}.sql"
  180. else
  181. output_sql="${BACKUP_DIR}/${db}-${TIMESTAMP}.sql"
  182. # Check whether database exists or not
  183. ${CMD_MYSQL} -u "$MYSQL_USER" --password="$MYSQL_PASSWD" --host="$MYSQL_HOST" --port="$MYSQL_PORT" --protocol="$MYSQL_PROTO" -e "use ${db}" &>/dev/null
  184. fi
  185.  
  186. if [ X"$?" == X'0' ]; then
  187. # Dump
  188. ${CMD_MYSQLDUMP} \
  189. -u "$MYSQL_USER" --password="$MYSQL_PASSWD" --host="$MYSQL_HOST" --port="$MYSQL_PORT" --protocol="$MYSQL_PROTO" \
  190. --default-character-set="$DB_CHARACTER_SET" \
  191. --triggers \
  192. --routines \
  193. --events \
  194. --single-transaction="$MYSQL_SINGLE_TX" \
  195. "$db" > "$output_sql" 2>/dev/null
  196.  
  197. # Compress
  198. if [ X"${COMPRESS}" == X"YES" ]; then
  199. ${CMD_COMPRESS} "${output_sql}" >> "${LOGFILE}"
  200.  
  201. if [ X"$?" == X'0' ] && [ X"${DELETE_PLAIN_SQL_FILE}" == X'YES' ]; then
  202. rm -f "${output_sql}" >> "${LOGFILE}"
  203. fi
  204. fi
  205. fi
  206. }
  207.  
  208. execute_backup() {
  209. # Date.
  210. YEAR="$(${CMD_DATE} +%Y)"
  211. MONTH="$(${CMD_DATE} +%m)"
  212. DAY="$(${CMD_DATE} +%d)"
  213. TIME="$(${CMD_DATE} +%H.%M.%S)"
  214. TIMESTAMP="${YEAR}.${MONTH}.${DAY}.${TIME}"
  215.  
  216. # Pre-defined backup status
  217. BACKUP_SUCCESS='YES'
  218.  
  219. # Define, check, create directories.
  220. BACKUP_DIR="${BACKUP_ROOTDIR}/${MYSQL_HOST}/${YEAR}/${MONTH}/${DAY}"
  221.  
  222. # Log file
  223. LOGFILE="${BACKUP_DIR}/${TIMESTAMP}.log"
  224.  
  225. # Check and create directories.
  226. [ ! -d "${BACKUP_DIR}" ] && mkdir -p "${BACKUP_DIR}" 2>/dev/null
  227.  
  228. # Initialize log file.
  229. echo "=============================================================================" > "${LOGFILE}"
  230. { echo "* Starting backup: ${TIMESTAMP}."; echo "* Backup directory: ${BACKUP_DIR}."; } >> "${LOGFILE}"
  231.  
  232.  
  233. # Backup.
  234. echo "* Backing up databases ..." >> "${LOGFILE}"
  235. sed -n 1,4p "${LOGFILE}"
  236. for db in ${DATABASES}; do
  237. backup_db "${db}" >> "${LOGFILE}"
  238.  
  239. if [ X"$?" == X"0" ]; then
  240. if [ "$db" = "--all-databases" ]; then
  241. echo " - ALL [DONE]" >> "${LOGFILE}"
  242. else
  243. echo " - ${db} [DONE]" >> "${LOGFILE}"
  244. fi
  245. else
  246. [ X"${BACKUP_SUCCESS}" == X"YES" ] && BACKUP_SUCCESS='NO'
  247. fi
  248. done
  249.  
  250. # Append file size of backup files.
  251. { echo -e "* File size:\n----"; ${CMD_DU} "${BACKUP_DIR}"/*"${TIMESTAMP}"*sql*; echo "----"; } >> "${LOGFILE}"
  252.  
  253. echo "* Backup completed (Success? ${BACKUP_SUCCESS})." >> "${LOGFILE}"
  254.  
  255. # if [ X"${BACKUP_SUCCESS}" == X"YES" ]; then
  256. # echo "==> Backup completed successfully."
  257. # else
  258. # echo -e "==> Backup completed with !!!ERRORS!!!.\n" 1>&2
  259. # fi
  260.  
  261. sed -n '5,$p' "$LOGFILE"
  262. }
  263.  
  264. if [ "$RUN_FREQ" = "NONSTOP" ]; then
  265. while true; do
  266. execute_backup
  267.  
  268. sleep "$SLEEP" &
  269. wait $!
  270. done
  271. elif [ "$RUN_FREQ" = "ONCE" ]; then
  272. execute_backup
  273. else
  274. echo "[ERROR] RUN_FREQ ENV can either be 'ONCE' or 'NONSTOP'." 1>&2
  275.  
  276. exit 255
  277. fi
  278.  
  279. exit 0
Add Comment
Please, Sign In to add comment