summaryrefslogtreecommitdiff
path: root/debian/mysql-common.preinst.in
blob: 362990bd130df2cfc3845dab9a954b1538d12b84 (plain)
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#!/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
}

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 >/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