Backup mysql binary logs

Developed In: bash — Contributed by: Partha Dutta

This script can be used to backup binary logs to a remote system. The script will also take into account all slave servers if you are backing up binary logs from the master, and will only backup completely processed binary logs. If a slave is behind on replication, or is stopped for some reason, then only the binary logs up to the lowest number processed by all slaves will be archived then purged.
Partha Dutta
bash
  1. #!/bin/sh
  2.  
  3. # mysqlbinlogbackup - backup binary logs
  4.  
  5. slave=
  6. slaves=
  7. slave_port=3306
  8. synch_with_slave=0
  9. opt_binlog_dir=0
  10. backup_host=localhost
  11. backup_port=3306
  12.  
  13. # Change below for the MySQL user/password used for admin purposes
  14. backup_user=backup_user
  15. backup_password=backup_password
  16.  
  17. binlog_dir=/var/lib/mysql/log/bin
  18. backup_dir=/var/tmp
  19.  
  20. # Change below to host where binlogs will be stored
  21. stored_backup_host=localhost
  22.  
  23. backup_host_dir=/var/backup/db
  24. log_file=/var/log/mysql/binlog_backup.log
  25. no_compress=0
  26. purge_only=0
  27. common_opts=
  28. transfer_delete=0
  29.  
  30. Log()
  31. {
  32. echo "`date` : $*" >> $log_file
  33. }
  34.  
  35. Usage()
  36. {
  37. cat << EOF_OPTIONS
  38. Usage : mysqlbinlogbackup options
  39.  
  40. --host Host to connect to (Default : $backup_host)
  41. --port Port to connect to (Default : $backup_port)
  42. --user User to connect to MySQL (Default : $backup_user)
  43. --password Password for user
  44. --slave Slave host to check binlog position
  45. (Specify multiple slaves by using --slave
  46. multiple times)
  47. --slave-port Port for slave host (Default : $slave_port)
  48. --binlog-dir Directory for binary logs
  49. --backup-dir Backup directory to store binary logs
  50. --backup-host Remote server for binary log storage
  51. (Default : localhost)
  52. --backup-host-dir Remote directory to store binary logs
  53. (Default : $backup_host_dir)
  54. --no-compress Do not perform compression
  55. --purge-only No backup, just purge binary logs.
  56. --no-transfer-delete Do not transfer or delete backup tgz file.
  57. EOF_OPTIONS
  58. }
  59.  
  60. parse_args()
  61. {
  62. for arg do
  63. case "$arg" in
  64. --host=*)
  65. backup_host=`echo "$arg" | sed -e 's/^[^=]*=//'`
  66. ;;
  67. --port=*)
  68. backup_port=`echo "$arg" | sed -e 's/^[^=]*=//'`
  69. ;;
  70. --user=*)
  71. backup_user=`echo "$arg" | sed -e 's/^[^=]*=//'`
  72. ;;
  73. --password=*)
  74. backup_password=`echo "$arg" | sed -e 's/^[^=]*=//'`
  75. ;;
  76. --slave=*)
  77. slave=`echo "$arg" | sed -e 's/^[^=]*=//'`
  78. if [ -z "$slaves" ]; then
  79. slaves=$slave
  80. else
  81. slaves="$slaves $slave"
  82. fi
  83. synch_with_slave=1;
  84. ;;
  85. --slave-port=*)
  86. slave_port=`echo "$arg" | sed -e 's/^[^=]*=//'`
  87. ;;
  88. --binlog-dir=*)
  89. binlog_dir=`echo "$arg" | sed -e 's/^[^=]*=//'`
  90. opt_binlog_dir=1
  91. ;;
  92. --backup-dir=*)
  93. backup_dir=`echo "$arg" | sed -e 's/^[^=]*=//'`
  94. ;;
  95. --backup-host=*)
  96. stored_backup_host=`echo "$arg" | sed -e 's/^[^=]*=//'`
  97. ;;
  98. --backup-host-dir=*)
  99. backup_host_dir=`echo "$arg" | sed -e 's/^[^=]*=//'`
  100. ;;
  101. --no-compress)
  102. no_compress=1
  103. ;;
  104. --purge-only)
  105. purge_only=1
  106. ;;
  107. --no-transfer-delete)
  108. transfer_delete=1
  109. ;;
  110. --help)
  111. Usage
  112. exit 0
  113. ;;
  114. -?)
  115. Usage
  116. exit 0
  117. ;;
  118. *)
  119. echo "Invalid argument $arg"
  120. Usage
  121. exit 1
  122. ;;
  123. esac
  124. done
  125. }
  126.  
  127. mysql_options()
  128. {
  129. common_opts="--user=$backup_user --password=$backup_password"
  130. if [ "$backup_host" != "localhost" ]; then
  131. common_opts="$common_opts --host=$backup_host --port=$backup_port"
  132. fi
  133. }
  134.  
  135. mysql_command()
  136. {
  137. mysql $common_opts --batch --skip-column-names $1 -e "$2"
  138. }
  139.  
  140.  
  141. ################################################################################
  142.  
  143. PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
  144. export PATH
  145.  
  146. parse_args $*
  147. mysql_options
  148.  
  149. # Find out what type of OS we are running on
  150. cat /proc/version | grep -i "red hat" > /dev/null
  151. if [ $? -eq 0 ]; then
  152. REDHAT=1
  153. else
  154. REDHAT=0
  155. fi
  156.  
  157. Log "[INIT] Starting MySQL binlog backup"
  158.  
  159. master_binlog=`mysql_command mysql "show master status" 2>/dev/null | cut -f1`
  160. Log "Current binary log is: $master_binlog"
  161.  
  162. if [ $synch_with_slave -eq 1 ]; then
  163. Log "Checking slaves' binary log execute pos"
  164. rm -f /var/tmp/binlogs.txt
  165. for i in $slaves
  166. do
  167. binlog=`mysql --host=$i --port=$slave_port --user=$backup_user --password=$backup_password --vertical mysql -e "show slave status" 2>/dev/null | grep "Relay_Master_Log_File" | awk '{print $2}'`
  168. if [ -z "$binlog" ]; then
  169. Log "Failed to retrieve binlog from $i"
  170. exit 1
  171. else
  172. Log "$i: $binlog"
  173. echo $binlog >> /var/tmp/binlogs.txt
  174. fi
  175. done
  176. slave_binlog=`sort /var/tmp/binlogs.txt | head -n 1`
  177. Log "Oldest slave binlog = $slave_binlog"
  178. if [ $slave_binlog != $master_binlog ]; then
  179. Log "Warning! Will use ${slave_binlog} instead of ${master_binlog} as current"
  180. master_binlog=$slave_binlog
  181. fi
  182. fi
  183.  
  184. if [ $purge_only -eq 1 ]; then
  185. Log "purge-only option set, Purging binary logs to $master_binlog"
  186. mysql_command mysql "purge master logs to '$master_binlog'"
  187. Log "[END] Backup complete"
  188. exit 0
  189. fi
  190.  
  191. first_log=
  192. last_log=
  193. copy_status=0
  194. backup_list=/tmp/binlog.list.$$
  195.  
  196. # Determine binlog dir
  197. if [ $opt_binlog_dir -eq 0 ]; then
  198. if [ $REDHAT -eq 1 ]; then
  199. bdir=`my_print_defaults -c /etc/my.cnf mysqld | grep "^\-\-log-bin=" | head -n 1`
  200. else
  201. bdir=`my_print_defaults -c /etc/mysql/my.cnf mysqld | grep "^\-\-log-bin=" | head -n 1`
  202. fi
  203. if [ $? -eq 0 ]; then
  204. binlog_dir=`echo $bdir | cut -d"=" -f2`
  205. binlog_dir=`dirname $binlog_dir`
  206. fi
  207. fi
  208.  
  209. Log "Flushing MySQL binary logs (FLUSH LOGS)"
  210. mysql_command mysql "flush logs"
  211.  
  212. for b in `mysql_command mysql "show master logs" | cut -f1`
  213. do
  214. if [ -z $first_log ]; then
  215. first_log=$b
  216. fi
  217. if [ $b != $master_binlog ]; then
  218. Log "Copying binary log ${b} to ${backup_dir}"
  219. cp $binlog_dir/$b $backup_dir >& /dev/null
  220. if [ $? -ne 0 ]; then
  221. copy_status=1
  222. break
  223. fi
  224. echo $b >> $backup_list
  225. last_log=$b
  226. else
  227. break
  228. fi
  229. done
  230.  
  231. if [ $copy_status -eq 1 ]; then
  232. Log "[ERR] Failed to copy binary logs cleanly...aborting"
  233. exit 1
  234. else
  235. # Tar them up
  236. cd $backup_dir
  237. tar_file=${backup_dir}/binlog.${first_log}.${last_log}.tar
  238. Log "Creating tar file $tar_file"
  239. tar cvf $tar_file -T $backup_list &> /dev/null
  240. if [ $? -eq 0 ]; then
  241. for b in `cat $backup_list`
  242. do
  243. /bin/rm -f $b
  244. done
  245. if [ $no_compress -eq 0 ]; then
  246. Log "Compressing tar file..."
  247. gzip $tar_file
  248. fi
  249. Log "Purging binary logs from MySQL system from $first_log to $master_binlog"
  250. mysql_command mysql "purge master logs to '$master_binlog'"
  251. else
  252. Log "[ERR] Failed to create tar archive"
  253. exit 1
  254. fi
  255. rm -f $backup_list
  256.  
  257. # Abort if we don't want to transfer or delete.
  258. if [ $transfer_delete -gt 0 ]; then
  259. exit 0
  260. fi
  261.  
  262. # Copy the tarball back to $stored_backup_host
  263. Log "Copying backup to $stored_backup_host:/$backup_host_dir"
  264. if [ $no_compress -eq 0 ]; then
  265. scp -q ${tar_file}.gz $stored_backup_host:/$backup_host_dir
  266. scp_status=$?
  267. else
  268. scp -q ${tar_file} $stored_backup_host:/$backup_host_dir
  269. scp_status=$?
  270. fi
  271. if [ $scp_status -eq 0 ]; then
  272. if [ $no_compress -eq 0 ]; then
  273. /bin/rm -f ${tar_file}.gz
  274. else
  275. /bin/rm -f $tar_file
  276. fi
  277. Log "[END] Backup complete"
  278. else
  279. Log "[ERR] Failed to copy backup file to $stored_backup_host"
  280. fi
  281. fi
  282.  

Current Tags

You must be logged in to tag this tool

Great script Partha.. Thank you

Votes

  • Rated 4.00 out of 5
Rated 4.00 out of 5 with 1 votes cast.
You must be logged in to vote.

Watches

5 members are watching this tool
You must be logged in to track this tool.

Provide Feedback

Please note:
HTML will be purified, but we allow for a number of HTML tags so that you have the flexibility to decorate your comment text to some extent. The comments allow the following HTML tags:

strong, b, em, blockquote, a, code, pre

To put code into your comment, simply encapsulate your code with
[code language="XXX"][/code], where XXX is any common language, for instance "PHP", "SQL", "C", etc.



You must be logged in to comment