mysql-server.preinst.in 4.98 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
#!/bin/bash -e
#
# summary of how this script can be called:
#        * <new-preinst> install
#        * <new-preinst> install <old-version>
#        * <new-preinst> upgrade <old-version>
#        * <old-preinst> abort-upgrade <new-version>
#

if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi
${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*" 1>&2 }

export PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin

# Try to stop the server in a sane way. If it does not success let the admin
# do it himself. No database directories should be removed while the server
# is running! Another mysqld in e.g. a different chroot is fine for us.
stop_server() {
    if [ ! -x /etc/init.d/mysql ]; then return; fi

    set +e
    if [ -x /usr/sbin/invoke-rc.d ]; then
      cmd="invoke-rc.d mysql stop"
    else
      cmd="/etc/init.d/mysql stop"
    fi
    $cmd
    errno=$?
    set -e
   
    # 0=ok, 100=no init script (fresh install)
    if [ "$errno" != 0 -a "$errno" != 100 ]; then
      echo "${cmd/ */} returned $errno" 1>&2
      echo "There is a MySQL server running, but we failed in our attempts to stop it." 1>&2
      echo "Stop it yourself and try again!" 1>&2
      exit 1
    fi
}

##### here's a bunch of helper functions for converting database formats ######

cvt_get_param(){
	/usr/sbin/mysqld --print-defaults \
		| tr " " "\n" \
		| grep -- "--$1" \
		| tail -n 1 \
		| cut -d= -f2
}

cvt_setup_stuff(){
	mytmp=`mktemp -d -t mysql-ISAM-convert.XXXXXX`
	cvt_log="$mytmp/conversion.log"
	if [ ! -d "$mytmp" ]; then
		echo "can't create temporary directory, oh well." >&2
		exit 1
	fi

	chgrp mysql $mytmp
	chmod g+rwx $mytmp
	cvt_socket=${mytmp}/mysql.sock

	cvt_mysqld="mysqld --skip-grant-tables --skip-networking --socket $cvt_socket"
	cvt_mysql="mysql --socket $cvt_socket"
	cvt_mysqladmin="mysqladmin --socket $cvt_socket"
}

cvt_get_databases(){
	echo fetching database list ... >&2
	$cvt_mysql -e 'show databases' | sed -n -e '2,$p'
}

cvt_get_tables(){
	echo querying tables in $1 ... >&2
	$cvt_mysql $1 -e 'show table status' | sed -n -e '2,$p' | \
		cut -f 1,2 | grep -w 'ISAM$' | cut -f 1
}

cvt_convert_table(){
	echo converting $1.$2 ... >&2
	$cvt_mysql $1 -e "alter table $2 type=MyISAM"
}

cvt_wait_for_server(){
	local count
	echo -n waiting for server startup.. >&2
	while ! $cvt_mysql </dev/null >/dev/null 2>&1; do
		echo -n . >&2
		sleep 1
		count=".$count"
		if [ -f $mytmp/mysql.done ]; then
			echo "sorry... looks like the server crashed :(" >&2
			return 1
		elif [ "$count" = "...................." ]; then
			echo "sorry... looks like the server didn't start :(" >&2
			return 1
		fi
	done
	echo ok. >&2
}

cvt_wait_for_exit(){
	local count
	echo -n waiting for server shutdown.. >&2
	while [ ! -f $mytmp/mysql.done ]; do
		echo -n . >&2
		sleep 1
		count=".$count"
		if [ "$count" = "...................." ]; then
			echo "hrm... guess it never started?" >&2
			return 0
		fi
	done
	echo ok. >&2
}

cvt_cleanup(){
	local mysql_kids
	rm -rf $mytmp
	# kill any mysqld child processes left over.  there *shouldn't* be any,
	# but let's not take chances with that
	mysql_kids=`ps o 'pid command' --ppid $$ | grep -E '^[[:digit:]]+ mysqld ' | cut -d' ' -f1`
	if [ "$mysql_kids" ]; then
		echo "strange, some mysql processes left around. killing them now." >&2
		kill $mysql_kids
		sleep 10
		mysql_kids=`ps o 'pid command' --ppid $$ | grep -E '^[[:digit:]]+ mysqld ' | cut -d' ' -f1`
		if [ "$mysql_kids" ]; then
			echo "okay, they're really not getting the hint..." >&2
			kill -9 $mysql_kids
		fi
	fi
}

################################ main() ##########################

# to be sure
stop_server

# test if upgrading from non conffile state
if [ "$1" = "upgrade" ] && [ -x /usr/sbin/mysqld ]; then
	cvt_datadir=`cvt_get_param datadir`
	# test for ISAM tables, which we must convert NOW
	if [ -n "`find $cvt_datadir -name '*.ISM' 2>/dev/null`" ]; then
		set +e
		cat << EOF >&2
----------------------------------------
WARNING WARNING WARNING
----------------------------------------

It has been detected that are are using ISAM format on some of your
mysql database tables.  This format has been deprecated and no longer
supported.  to prevent these databases from essentially disappearing,
an attempt at format conversion will now be made.  please check after
your upgrade that all tables are present and accounted for.

apologies for the noise, but we thought you'd appreciate it :)

----------------------------------------
WARNING WARNING WARNING
----------------------------------------
EOF
		cvt_setup_stuff
		($cvt_mysqld >$cvt_log 2>&1; touch $mytmp/mysql.done ) &

		if cvt_wait_for_server; then
			dbs=`cvt_get_databases`
			for db in $dbs; do
				tables=`cvt_get_tables $db`
				for tbl in $tables; do
					cvt_convert_table $db $tbl
				done
			done
		else
			cvt_error="yes"
		fi

		echo shutting down server... >&2
		$cvt_mysqladmin shutdown
		cvt_wait_for_exit
		echo "all done!" >&2
		if [ ! "$cvt_error" = "yes" ]; then
			cvt_cleanup
		else
			echo "you might want to look in $mytmp..." >&2
		fi

		set -e
	fi
fi

exit 0