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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
|
#!/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>
#
# shellcheck source=/dev/null
. /usr/share/debconf/confmodule
# Just kill the invalid insserv.conf.d directory without fallback
if [ -d "/etc/insserv.conf.d/mariadb/" ]
then
rm -rf "/etc/insserv.conf.d/mariadb/"
fi
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
mysql_datadir=/var/lib/mysql
mysql_upgradedir=/var/lib/mysql-upgrade
MARIADBD_USERS="root"
# Check if user 'mysql' exists before referring to it in pgrep
# to avoid pgrep erroring on 'invalid user name'
if id mysql >/dev/null 2>&1
then
MARIADBD_USERS="$MARIADBD_USERS,mysql"
fi
# 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 mariadbd in e.g. a different chroot is fine for us.
stop_server() {
# Return immediately if there are no mysqld processes running on a host
# (leave containerized processes with the same name in other namespaces)
# as there is no point in trying to shutdown in that case.
if ! pgrep -x -u "$MARIADBD_USERS" --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null
then
return
fi
set +e
invoke-rc.d mariadb stop
invoke-rc.d mysql stop # Backwards compatibility
errno=$?
set -e
# systemctl could emit exit code 100=no init script (fresh install)
if [ "$errno" != 0 ] && [ "$errno" != 100 ]
then
echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2
echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2
echo "Stop it yourself and try again!" 1>&2
db_stop
exit 1
fi
}
################################ main() ##########################
# @TODO: Rewrite this to use the new upstream /var/lib/mysql_upgrade_info file
# instead of the legacy /var/lib/debian-XX.X.flag file
this_version=__MARIADB_MAJOR_VER__
max_upgradeable_version=5.7
# Check if a flag file is found that indicates a previous MariaDB or MySQL
# version was installed. If multiple flags are found, check which one was
# the biggest version number.
for flag in "$mysql_datadir"/debian-*.flag
do
# The for loop leaves $flag as the query string if there are no results,
# so the check below is needed to stop further processing when there are
# no real results.
if [ "$flag" = "$mysql_datadir/debian-*.flag" ]
then
break
fi
# The whole flag_version thing should be rewritten, so ignore minor Shellcheck
# nag for now
# shellcheck disable=SC2001
flag_version=$(echo "$flag" | sed 's/.*debian-\([0-9\.]\+\).flag/\1/')
# Initialize value if empty
if [ -z "$found_version" ]
then
found_version=$flag_version
fi
# Update value if now bigger then before
if dpkg --compare-versions "$flag_version" '>>' "$found_version"
then
found_version=$flag_version
fi
done
# If an upgrade is detected, proceed with it automatically without
# requiring any user interaction.
#
# However, if the user attempts to downgrade, warn about the incompatibility.
# Downgrade is detected if the flag version is bigger than $this_version
# (e.g. 10.1 > 10.0) or the flag version is smaller than 10.0 but bigger
# than $max_upgradeable_version.
if [ -n "$found_version" ]
then
# MySQL 8.0 in Ubuntu has a bug in packaging and the file is name wrongly
# 'debian-5.7.flag', so in case '5.7' was encountered an extra check needs to
# be done to see is there is a file called undo_001, which is a sign of 8.0.
if [ "$found_version" == "5.7" ] && [ -f "$mysql_datadir/undo_001" ]
then
# Seems to be a 8.0, flag has wrongly 5.7 (know bug)
found_version=8.0
fi
echo "$mysql_datadir: found previous version $found_version"
if dpkg --compare-versions "$found_version" '>>' "$this_version"
then
downgrade_detected=true
fi
if dpkg --compare-versions "$found_version" '>>' "$max_upgradeable_version" \
&& dpkg --compare-versions "$found_version" '<<' "10.0"
then
downgrade_detected=true
fi
fi
# If there is no debian-*.flag, and no version was detected, but a file that
# indicated MySQL 8.0 is found (undo_001 is created by default in MySQL 8.0+
# installs), then that file is enough of additional indication to trigger the
# move of the data directory.
if [ -z "$found_version" ] &&
[ -z "$(find $mysql_datadir/debian-*.flag 2> /dev/null)" ] &&
[ -f "$mysql_datadir/undo_001" ]
then
echo "$mysql_datadir: no server version flag found, assuming MySQL 8.0 data encountered" 1>&2
downgrade_detected=true
found_version="previous" # Just use dummy name as we don't know real version
fi
# Don't abort dpkg if downgrade is detected (as was done previously).
# Instead simply move the old datadir and create a new for this_version.
if [ -n "$downgrade_detected" ]
then
db_input critical "mariadb-server/old_data_directory_saved" || true
db_go
echo "The contents of $mysql_datadir/ indicates a" 1>&2
echo "version that cannot automatically be upgraded. Therefore the" 1>&2
echo "previous data directory will be renamed to $mysql_datadir-$found_version and" 1>&2
echo "a new data directory will be initialized at $mysql_datadir." 1>&2
echo "Please manually export/import your data (e.g. with mysqldump) if needed." 1>&2
mv -f "$mysql_datadir" "$mysql_datadir-$found_version"
# Also move away the old debian.cnf file that included credentials that are
# no longer valid. If none existed, ignore error and let dpkg continue.
mv -f /etc/mysql/debian.cnf "/etc/mysql/debian.cnf-$found_version" || true
fi
# to be sure
stop_server
# If we use NIS then errors should be tolerated. It's up to the
# user to ensure that the mysql user is correctly setup.
# Beware that there are two ypwhich one of them needs the 2>/dev/null!
if test -n "$(command -v ypwhich 2>/dev/null)" && ypwhich > /dev/null 2>&1
then
set +e
fi
#
# Now we have to ensure the following state:
# /etc/passwd: mysql:x:100:101:MariaDB Server:/nonexistent:/bin/false
# /etc/group: mysql:x:101:
#
# Sadly there could any state be present on the system so we have to
# modify everything carefully i.e. not doing a chown before creating
# the user etc...
#
# creating mysql group if he isn't already there
if ! getent group mysql >/dev/null
then
# Adding system group: mysql.
addgroup --system mysql >/dev/null
fi
# creating mysql user if he isn't already there
if ! getent passwd mysql >/dev/null
then
# Adding system user: mysql.
adduser \
--system \
--disabled-login \
--ingroup mysql \
--no-create-home \
--home /nonexistent \
--gecos "MariaDB Server" \
--shell /bin/false \
mysql >/dev/null 2>&1
fi
# end of NIS tolerance zone
set -e
# if there's a symlink, let's store where it's pointing, because otherwise
# it's going to be lost in some situations
for dir in DATADIR LOGDIR
do
checkdir=$(eval echo "$"$dir)
if [ -L "$checkdir" ]
then
# Use mkdir option 'Z' to create with correct SELinux context.
mkdir -pZ "$mysql_upgradedir"
cp -dT "$checkdir" "$mysql_upgradedir/$dir.link"
fi
done
# creating mysql home directory
if [ ! -d $mysql_datadir ] && [ ! -L $mysql_datadir ]
then
# Use mkdir option 'Z' to create with correct SELinux context.
mkdir -Z $mysql_datadir
fi
# As preset blocksize of GNU df is 1024 then available bytes is $df_available_blocks * 1024
# 4096 blocks is then lower than 4 MB
df_available_blocks="$(LC_ALL=C BLOCKSIZE='' df --output=avail "$mysql_datadir" | tail -n 1)"
if [ "$df_available_blocks" -lt "4096" ]
then
echo "ERROR: There's not enough space in $mysql_datadir/" 1>&2
db_stop
exit 1
fi
# Since the home directory was created before putting the user into
# the mysql group and moreover we cannot guarantee that the
# permissions were correctly *before* calling this script, we fix them now.
# In case we use NIS and no mysql user is present then this script should
# better fail now than later..
# The "set +e" is necessary as e.g. a ".journal" of a ext3 partition is
# not chgrp'able (#318435).
set +e
find $mysql_datadir ! -uid "$(id -u mysql)" -print0 | xargs -0 -r chown mysql
find $mysql_datadir -follow -not -group mysql -print0 2>/dev/null \
| xargs -0 --no-run-if-empty chgrp mysql
set -e
db_stop
#DEBHELPER#
# dh_installinit/13.11.3 adds this check but only with 'install', so we need to
# have and extra one to check 'upgrade'. This ensures that upgrades from
# mariadb-server-x.y to mariadb-server (without version suffix) ends up with
# the executable bit set on /etc/init.d/mariadb, which otherwise would end up
# disabled due to the mariadb-server-x.y.postrm being triggered.
# $1 = upgrade
# $2 = 1:10.6.11-2
if [ "$1" = "upgrade" ] && [ -n "$2" ] && [ -e "/etc/init.d/mariadb" ]
then
chmod +x "/etc/init.d/mariadb" >/dev/null || true
fi
# dh_installinit/13.11.3 adds this check but with extra condition that there
# must be a version passed as '$2', but that will always be empty when install
# runs after the unpack that is retriggered for package 'mariadb-server' when
# the old 'mariadb-server-10.6' is purged, so we need to repeat the same check
# here without any expectation for '$2'. This ensures that upgrades from
# mariadb-server-x.y to mariadb-server (without version suffix) ends up with the
# executable bit set on /etc/init.d/mariadb.
if [ "$1" = "install" ] && [ -e "/etc/init.d/mariadb" ]
then
chmod +x "/etc/init.d/mariadb" >/dev/null || true
fi
|