#!/bin/sh # Flush MySQL tables to the disk before the filesystem is frozen. # At the same time, this keeps a read lock in order to avoid write accesses # from the other clients until the filesystem is thawed. MYSQL="/usr/bin/mysql" MYSQL_OPTS="-uroot" #"-prootpassword" FIFO=/var/run/mysql-flush.fifo # Check mysql is installed and the server running [ -x "$MYSQL" ] && "$MYSQL" $MYSQL_OPTS < /dev/null || exit 0 flush_and_wait() { printf "FLUSH TABLES WITH READ LOCK \\G\n" trap 'printf "$(date): $0 is killed\n">&2' HUP INT QUIT ALRM TERM read < $FIFO printf "UNLOCK TABLES \\G\n" rm -f $FIFO } case "$1" in freeze) mkfifo $FIFO || exit 1 flush_and_wait | "$MYSQL" $MYSQL_OPTS & # wait until every block is flushed while [ "$(echo 'SHOW STATUS LIKE "Key_blocks_not_flushed"' |\ "$MYSQL" $MYSQL_OPTS | tail -1 | cut -f 2)" -gt 0 ]; do sleep 1 done # for InnoDB, wait until every log is flushed INNODB_STATUS=$(mktemp /tmp/mysql-flush.XXXXXX) [ $? -ne 0 ] && exit 2 trap "rm -f $INNODB_STATUS; exit 1" HUP INT QUIT ALRM TERM while :; do printf "SHOW ENGINE INNODB STATUS \\G" |\ "$MYSQL" $MYSQL_OPTS > $INNODB_STATUS LOG_CURRENT=$(grep 'Log sequence number' $INNODB_STATUS |\ tr -s ' ' | cut -d' ' -f4) LOG_FLUSHED=$(grep 'Log flushed up to' $INNODB_STATUS |\ tr -s ' ' | cut -d' ' -f5) [ "$LOG_CURRENT" = "$LOG_FLUSHED" ] && break sleep 1 done rm -f $INNODB_STATUS ;; thaw) [ ! -p $FIFO ] && exit 1 echo > $FIFO ;; *) exit 1 ;; esac