#!/bin/bash -e # # summary of how this script can be called: # * install # * install # * upgrade # * abort-upgrade # 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 } start_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 start" else cmd="/etc/init.d/mysql start" fi $cmd set -e } ##### 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 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() ########################## # 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 pidfile=`cvt_get_param pid-file` if [ "$pidfile" ] && [ -f "$pidfile" ]; then server_pid=`cat $pidfile` if [ "$server_pid" ] && ps $server_pid >/dev/null 2>&1; then server_running="yes" fi fi # to be sure stop_server 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 if [ "$server_running" ]; then start_server fi set -e fi fi exit 0