1#!/bin/sh
2
3# Flush MySQL tables to the disk before the filesystem is frozen.
4# At the same time, this keeps a read lock in order to avoid write accesses
5# from the other clients until the filesystem is thawed.
6
7MYSQL="/usr/bin/mysql"
8MYSQL_OPTS="-uroot" #"-prootpassword"
9FIFO=/var/run/mysql-flush.fifo
10
11# Check mysql is installed and the server running
12[ -x "$MYSQL" ] && "$MYSQL" $MYSQL_OPTS < /dev/null || exit 0
13
14flush_and_wait() {
15    printf "FLUSH TABLES WITH READ LOCK \\G\n"
16    trap 'printf "$(date): $0 is killed\n">&2' HUP INT QUIT ALRM TERM
17    read < $FIFO
18    printf "UNLOCK TABLES \\G\n"
19    rm -f $FIFO
20}
21
22case "$1" in
23    freeze)
24        mkfifo $FIFO || exit 1
25        flush_and_wait | "$MYSQL" $MYSQL_OPTS &
26        # wait until every block is flushed
27        while [ "$(echo 'SHOW STATUS LIKE "Key_blocks_not_flushed"' |\
28                 "$MYSQL" $MYSQL_OPTS | tail -1 | cut -f 2)" -gt 0 ]; do
29            sleep 1
30        done
31        # for InnoDB, wait until every log is flushed
32        INNODB_STATUS=$(mktemp /tmp/mysql-flush.XXXXXX)
33        [ $? -ne 0 ] && exit 2
34        trap "rm -f $INNODB_STATUS; exit 1" HUP INT QUIT ALRM TERM
35        while :; do
36            printf "SHOW ENGINE INNODB STATUS \\G" |\
37                "$MYSQL" $MYSQL_OPTS > $INNODB_STATUS
38            LOG_CURRENT=$(grep 'Log sequence number' $INNODB_STATUS |\
39                          tr -s ' ' | cut -d' ' -f4)
40            LOG_FLUSHED=$(grep 'Log flushed up to' $INNODB_STATUS |\
41                          tr -s ' ' | cut -d' ' -f5)
42            [ "$LOG_CURRENT" = "$LOG_FLUSHED" ] && break
43            sleep 1
44        done
45        rm -f $INNODB_STATUS
46        ;;
47
48    thaw)
49        [ ! -p $FIFO ] && exit 1
50        echo > $FIFO
51        ;;
52
53    *)
54        exit 1
55        ;;
56esac
57