]> git.pld-linux.org Git - packages/mysql.git/blob - mysql.init
- revamped database init:
[packages/mysql.git] / mysql.init
1 #!/bin/sh
2 #
3 # mysql         A very fast and reliable SQL database engine
4 #
5 # chkconfig:    2345 84 25
6 #
7 # description:  A very fast and reliable SQL database engine.
8 #
9 # $Id$
10
11 # Source function library
12 . /etc/rc.d/init.d/functions
13
14 # Get network config
15 . /etc/sysconfig/network
16
17 # Get service config
18 if [ -f /etc/sysconfig/mysql ]; then
19         . /etc/sysconfig/mysql
20 else
21         nls "Error: %s not found" /etc/sysconfig/mysql
22         nls "%s can't be run." MySQL
23         exit 1
24 fi
25
26 if [ -n "$MYSQL_DB_CLUSTERS" ]; then
27         nls "Warning: MYSQL_DB_CLUSTERS is set. It's obsolete. Use %s instead." /etc/mysql/clusters.conf
28 fi
29
30 if [ -f /etc/mysql/clusters.conf ]; then
31         MYSQL_DB_CLUSTERS=$(awk -F= '!/^#/{print $2}' /etc/mysql/clusters.conf)
32         if [ -z "$MYSQL_DB_CLUSTERS"  ]; then
33                 nls "Warning: there are no configured clusters."
34         fi
35
36 else
37         nls "Warning: Missing clusters config file %s" /etc/mysql/clusters.conf
38         if [ -z "$MYSQL_DB_CLUSTERS"  ]; then
39                 nls "Warning: there are no configured clusters."
40                 nls "Using default cluster /var/lib/mysql (compatibility mode)"
41                 MYSQL_DB_CLUSTERS=/var/lib/mysql
42         fi
43 fi
44
45
46 # Check that networking is up
47 if is_yes "${NETWORKING}"; then
48         if [ ! -f /var/lock/subsys/network -a "$1" != stop -a "$1" != status -a "$1" != init ]; then
49                 msg_network_down MySQL
50                 exit 1
51         fi
52 else
53         exit 0
54 fi
55
56 action="$1"
57
58 # any db cluster as command line argument?
59 if [ $# -gt 1 ]; then
60         shift
61         # perform action for specified clusters only
62         for a in "$@"; do
63                 # try auto resolving from /etc/mysql/clusters.conf
64                 if [[ "$a" != /* ]]; then
65                         m=$(awk -va="$a" -F= 'substr($0, 1, length(a)) == a {print $1}' /etc/mysql/clusters.conf)
66                         if [ -z "$m" ]; then
67                                 echo >&2 "Cluster name '$a' did not match anything!"
68                                 exit 1
69                         fi
70                         if [ $(echo "$m" | wc -l) -gt 1 ]; then
71                                 echo >&2 "Cluster name '$a' ambiguous:" $m
72                                 exit 1
73                         fi
74                         a=$(awk -va="$a" -F= 'substr($0, 1, length(a)) == a {print $2}' /etc/mysql/clusters.conf)
75                 fi
76                 DB_CLUSTERS="$DB_CLUSTERS $a"
77         done
78 else
79         DB_CLUSTERS="$MYSQL_DB_CLUSTERS"
80 fi
81
82 MYSQL_ERRLOG=/var/log/mysql/err
83 MYSQL_START_WAIT_TIME=${MYSQL_START_WAIT_TIME:-15}
84 MYSQL_STOP_WAIT_TIME=${MYSQL_STOP_WAIT_TIME:-900}
85
86 #
87 # Useful functions.
88 #
89
90 #
91 # check for mysql status
92 #
93 # arguments:
94 # $1 - db cluster
95 # $2 - start|stop
96 #
97 # sets variables:
98 # MYSQL_STATUS = starting | running | not running | died
99 # MYSQL_PID    = pid of mysqld process
100 #
101 mysqlstatus() {
102         clusterdir="$1"
103         mode="$2"
104         
105         mysqlgetconfig "$clusterdir"
106
107         MYSQL_STATUS="not running"
108         MYSQL_PID="unknown"
109         MYSQL_PIDFILE_PID=""
110         MYSQL_GREP_PID=""
111
112         if [ -f "$MYSQL_PIDFILE" ]; then
113                 MYSQL_PIDFILE_PID=$(cat "$MYSQL_PIDFILE")
114         fi
115         
116         if [ -n "$MYSQL_PIDFILE_PID" ]; then
117                 MYSQL_PID=$MYSQL_PIDFILE_PID
118                 if [ ! -d "/proc/$MYSQL_PID" ]; then
119                         MYSQL_STATUS="died"
120                         return
121                 elif (grep -qa "$MYSQL_PIDFILE" /proc/$MYSQL_PID/cmdline 2> /dev/null); then
122                         MYSQL_STATUS="running"
123                         return
124                 fi
125         fi
126
127         if [ "$mode" = "start" ]; then
128                 MYSQL_GREP_PID=$(grep -lE "^/usr/sbin/mysqld.*${MYSQL_PIDFILE}" /proc/[0-9]*/cmdline 2> /dev/null | awk -F "/" '{ print $3; exit; }')
129                 if [ -n "$MYSQL_GREP_PID" ]; then
130                         MYSQL_PID=$MYSQL_GREP_PID
131                         if grep -qa "$MYSQL_PIDFILE" /proc/$MYSQL_PID/cmdline 2> /dev/null; then
132                                 if [ -f "$MYSQL_PIDFILE" ]; then
133                                         MYSQL_PIDFILE_PID=$(cat "$MYSQL_PIDFILE")
134                                 fi
135                                 if [ -n "$MYSQL_PIDFILE_PID" ]; then
136                                         MYSQL_PID=$MYSQL_PIDFILE_PID
137                                         MYSQL_STATUS="running"
138                                         return
139                                 else
140                                         MYSQL_STATUS="starting"
141                                         return
142                                 fi
143                         fi
144                 fi
145         fi
146
147         # else default, "not running"
148 }
149
150 # get mysql configuration in variables
151 # MYSQL_CONFIG MYSQL_DATA_DIR MYSQL_USER MYSQL_PIDFILE
152 #
153 # arguments
154 # $1 - db cluster
155
156 mysqlgetconfig() {
157         clusterdir="$1"
158
159         # emulate old behaviour if only one cluster specified
160         if [ "$clusterdir" = "$MYSQL_DB_CLUSTERS" -a "$clusterdir" = "/var/lib/mysql" -a -f /etc/mysqld.conf ]; then
161                 MYSQL_RA_COMPAT=yes
162                 config_file=/etc/mysqld.conf
163         else
164                 config=$(awk -F= -vclusterdir="$clusterdir" '!/^#/{ if (clusterdir == $2) print $1}' /etc/mysql/clusters.conf)
165                 if [[ $config = /* ]]; then
166                         config_file="$config"
167                 elif [ -f "/etc/mysql/$config" ]; then
168                         config_file="/etc/mysql/$config"
169                 else
170                         config_file="$clusterdir/mysqld.conf"
171                 fi
172         fi
173
174         MYSQL_CLUSTER_DIR="$clusterdir"
175
176         if [ -z "$config_file" ]; then
177                 nls "Error: Can't find config file for %s cluster" "$clusterdir"
178                 exit 6
179         else
180                 MYSQL_CONFIG="$config_file"
181         fi
182
183         if [ ! -f "$config_file" ]; then
184                 nls "Error: config file %s not found" "$config_file"
185                 nls "MySQL can't be run. Did you initialize DB by doing \`$0 init'?"
186                 exit 6
187         fi
188
189         eval `awk '
190 /^[ \t]*\[.*\][ \t]*$/ {
191         match($0,/\[.*\]/)
192         section=substr($0, RSTART + 1, RSTART + RLENGTH - 3)
193 }
194 section == "mysqld" && $2 ~ "=" {
195         if ($1 == "datadir") {
196                 printf("MYSQL_DATA_DIR=%s;", $3)
197         } else if ($1 == "user") {
198                 printf("MYSQL_USER=%s;", $3)
199         } else if ($1 == "pid-file") {
200                 printf("MYSQL_PIDFILE=%s;", $3)
201         } else if ($1 == "socket") {
202                 printf("MYSQL_SOCKET=%s;", $3)
203         }
204 }
205 ' $config_file`
206
207
208         if is_yes "$MYSQL_RA_COMPAT"; then
209                 MYSQL_DATA_DIR_SUB=""
210         else
211                 MYSQL_DATA_DIR_SUB="/mysqldb"
212         fi
213
214         if [ -z "$MYSQL_DATA_DIR" -o "$MYSQL_DATA_DIR" != "${clusterdir}${MYSQL_DATA_DIR_SUB}/db" ]; then
215                 nls "Error: datadir specified in %s should be %s" "$config_file" "$clusterdir${MYSQL_DATA_DIR_SUB}/db"
216                 nls " MySQL can't be run."
217                 exit 6
218         fi
219
220         if [ -z "$MYSQL_PIDFILE" -o "$MYSQL_PIDFILE" != "$clusterdir${MYSQL_DATA_DIR_SUB}/mysql.pid" ]; then
221                 nls "Error: pid-file specified in %s should be %s" "$config_file" "$clusterdir${MYSQL_DATA_DIR_SUB}/mysql.pid"
222                 nls " MySQL can't be run."
223                 exit 6
224         fi
225
226         if [ -z $MYSQL_USER ]; then
227                 echo "$(nls 'MySQL user not configured properly')"'!' >&2
228                 nls "Edit %s and configure it." "$config_file" >&2
229                 exit 6
230         fi
231 }
232
233 # start mysql
234 mysqlstart() {
235         clusterdir="$1"
236         mysqlgetconfig "$clusterdir"
237         if [ ! -d "$MYSQL_DATA_DIR/mysql" ]; then
238                 nls "MySQL cluster %s not initialized." "$clusterdir"
239                 nls "Try \`%s init %s' before start." "$0" "$clusterdir"
240                 exit 6
241         fi
242
243         msg_starting "MySQL $clusterdir"
244         busy
245         [ -z "$DEFAULT_SERVICE_RUN_NICE_LEVEL" ] && DEFAULT_SERVICE_RUN_NICE_LEVEL=0
246         rm -f "$MYSQL_PIDFILE"
247
248         TMPDIR=/tmp nice -n ${SERVICE_RUN_NICE_LEVEL:-$DEFAULT_SERVICE_RUN_NICE_LEVEL} \
249                 /usr/bin/setsid /usr/sbin/mysqld \
250                         --defaults-file=$MYSQL_CONFIG \
251                         --datadir=$MYSQL_DATA_DIR \
252                         --pid-file=$MYSQL_PIDFILE $MYSQL_OPTIONS \
253                 >> $MYSQL_ERRLOG 2>&1 &
254         pid=$!
255
256         sleep 0.1
257         mysqlstatus "$clusterdir" start
258         # it takes longer for mysqld to start and create pidfile if it has to recover innodb transactions
259         if [ "$MYSQL_STATUS" = "starting" ]; then
260                 echo ""
261                 show "Waiting for MySQL to start"
262                 busy
263
264                 # while the pid is running, mysql is starting up
265                 # if the pidfile was created, it started up successfully
266                 # if either case fails we break and report status
267                 while true; do
268                         [ -d /proc/$pid ] || break
269                         [ -f "$MYSQL_PIDFILE" ] && break
270                         sleep 0.2
271                 done
272         fi
273
274         mysqlstatus "$clusterdir" start
275         if [ "$MYSQL_STATUS" = "running" -a "$MYSQL_PID" != "unknown" ]; then
276                 ok
277         elif [ "$MYSQL_STATUS" = "died" ]; then
278                 RETVAL=1
279                 died
280         else
281                 RETVAL=1
282                 fail
283         fi
284 }
285
286 # stop mysql
287 mysqlstop() {
288         clusterdir="$1"
289         mysqlstatus "$clusterdir" stop
290         msg_stopping "MySQL $clusterdir"
291         busy
292
293         # try graceful shutdown -- send shutdown command
294         # requires mysql_sysadmin user proper privs
295         /usr/bin/mysqladmin --defaults-file=$MYSQL_CONFIG ${MYSQL_SOCKET:+--socket=$MYSQL_SOCKET} shutdown >/dev/null 2>&1
296         mysqlstatus "$clusterdir" stop
297
298         if [ "$MYSQL_PID" != "unknown" ]; then
299                 kill -TERM "$MYSQL_PID" 2> /dev/null
300                 for nr in $(seq 1 $(($MYSQL_STOP_WAIT_TIME*10))); do
301                         [ -d "/proc/$MYSQL_PID" ] || break
302                         sleep 0.1
303                 done
304         fi
305         
306         mysqlstatus "$clusterdir" stop
307         if [ "$MYSQL_STATUS" = "died" ]; then
308                 died
309         elif [ "$MYSQL_STATUS" = "running" -o "$MYSQL_STATUS" = "starting" ]; then
310                 fail
311         else
312                 ok
313         fi
314 }
315
316 #
317 # check for running mysql instances; if any instance is running then
318 # create subsys lock file
319 #
320 mysqlsubsys() {
321         # check for every defined db cluster in sysconfig file
322         for mysqldir in $DB_CLUSTERS; do
323                 mysqlstatus "$mysqldir"
324                 if [ "$MYSQL_STATUS" = "running" ]; then
325                         touch /var/lock/subsys/mysql
326                         return
327                 fi
328         done
329         rm -f /var/lock/subsys/mysql
330 }
331
332 mysqlinit() {
333         clusterdir="$1"
334
335         if [ -f /etc/mysqld.conf ]; then
336                 nls "Running in \`no cluster compat' mode: can't initialize database."
337                 nls "Move /etc/mysqld.conf away and rerun \`$0 init' (new config will be in $clusterdir)."
338                 exit 1
339         fi
340
341         if [ -f "$clusterdir/mysqld.conf" ]; then
342                 mysqlgetconfig "$clusterdir"
343         else
344                 MYSQL_USER="mysql"
345                 MYSQL_CLUSTER_DIR="$clusterdir"
346                 MYSQL_DATA_DIR="$clusterdir/mysqldb/db"
347                 MYSQL_PIDFILE="$clusterdir/mysqldb/mysql.pid"
348                 MYSQL_SOCKET="$clusterdir/mysqldb/mysql.sock"
349
350                 # this $MYSQL_CONFIG will be created later
351                 MYSQL_CONFIG="$MYSQL_CLUSTER_DIR/mysqld.conf"
352         fi
353
354         show "Initializing cluster %s" "$clusterdir"; echo
355
356         # Check if not exist init database
357         if [ -d "$MYSQL_DATA_DIR/mysql" ]; then
358                 nls "Seems that database is initialized now. Remove by hand %s" "$MYSQL_DATA_DIR/mysql"
359                 nls "before initializing database."
360                 nls "For now skipping cluster %s." "$clusterdir"
361                 return
362         fi
363
364         show "Installing MySQL system tables for $MYSQL_DATA_DIR"
365         busy
366         TMP=/tmp TMPDIR=/tmp
367
368         mkdir -p "$MYSQL_DATA_DIR" > /dev/null 2>&1
369         # Using mysql:mysql for MYSQL_CLUSTER_DIR is creating SECURITY hole, root:root is proper
370         chown root:root "$MYSQL_CLUSTER_DIR"
371         chown mysql:mysql "$MYSQL_CLUSTER_DIR/mysqldb" "$MYSQL_DATA_DIR" > /dev/null 2>&1
372         chmod 751 "$MYSQL_CLUSTER_DIR" "$MYSQL_CLUSTER_DIR/mysqldb"
373
374         if [ -f /usr/share/mysql/mysqld.conf -a ! -f "$MYSQL_CLUSTER_DIR/mysqld.conf" ]; then
375             sed -e "
376                 s#\(datadir.*\)=.*#\1= $MYSQL_DATA_DIR#g;
377                 s#\(pid-file.*\)=.*#\1= $MYSQL_PIDFILE#g;
378                 s#\(socket.*\)=.*#\1= $MYSQL_SOCKET#g;
379                 s#@clusterdir@#$MYSQL_CLUSTER_DIR#g;
380                 " /usr/share/mysql/mysqld.conf > "$MYSQL_CLUSTER_DIR/mysqld.conf"
381             chown root:root "$MYSQL_CLUSTER_DIR/mysqld.conf"
382             chmod 640 "$MYSQL_CLUSTER_DIR/mysqld.conf"
383         fi
384
385         if [ ! -e /var/lib/mysql/mysql.sock ] || [ -L /var/lib/mysql/mysql.sock ] && [ -z "$(readlink /var/lib/mysql/mysql.sock)" ]; then
386                 sock=${MYSQL_SOCKET#/var/lib/mysql/} # make it relative if possible
387             ln -s "$sock" /var/lib/mysql/mysql.sock
388         fi
389
390         cat > $MYSQL_DATA_DIR/mysql-init.sql <<-EOF
391                 CREATE DATABASE mysql;
392                 use mysql;
393                 $(cat /usr/share/mysql/mysql_system_tables.sql)
394                 $(sed -e "/@current_hostname/d" /usr/share/mysql/mysql_system_tables_data.sql)
395 EOF
396
397         ok=0
398         /usr/sbin/mysqld --bootstrap --skip-grant-tables \
399                 --datadir=$MYSQL_DATA_DIR --user=$MYSQL_USER \
400                 --slave-load-tmpdir=$MYSQL_DATA_DIR --tmpdir=$MYSQL_DATA_DIR < \
401                 $MYSQL_DATA_DIR/mysql-init.sql 2>> /var/log/mysql/err && ok=1
402         [ -f $MYSQL_DATA_DIR/mysql/host.frm ] || ok=0
403
404         if [ "$ok" = 1 ]; then
405                 rm -f $MYSQL_DATA_DIR/mysql-init.sql
406                 ok
407                 cat << END_OF_MSG
408
409 PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL USERS!
410 This is done, after starting database, in the order shown,
411 with:
412
413 For 'mysql_sysadmin' (RELOAD and SHUTDOWN privileges):
414 echo "update mysql.user set password=password('newpassword') where user='mysql_sysadmin'; FLUSH PRIVILEGES;" | mysql -u mysql -S $MYSQL_SOCKET
415
416 For 'mysql' user (ALL privileges, DB admin):
417 echo "update mysql.user set password=password('newpassword') where user='mysql'; FLUSH PRIVILEGES;" | mysql -u mysql -S $MYSQL_SOCKET
418
419 NOTE: mysql_sysadmin password should be placed to $MYSQL_CONFIG in
420 mysqladmin section. See the manual for more instructions.
421 (This user is used at logs rotation and server shutdown)
422
423 END_OF_MSG
424                 show "Filling help tables..."
425                 ok=0
426                 ( echo "use mysql;"; cat /usr/share/mysql/fill_help_tables.sql ) | \
427                         /usr/sbin/mysqld --bootstrap --skip-grant-tables \
428                         --datadir=$MYSQL_DATA_DIR --user=$MYSQL_USER \
429                         --slave-load-tmpdir=$MYSQL_DATA_DIR --tmpdir=$MYSQL_DATA_DIR < \
430                         $MYSQL_DATA_DIR/mysql-init.sql 2>> /var/log/mysql/err && ok=1
431                 if [ "$ok" = 1 ]; then
432                         ok
433                 else
434                         cat << END_OF_MSG
435
436 WARNING: HELP FILES ARE NOT COMPLETELY INSTALLED!
437 The "HELP" command might not work properly.
438
439 END_OF_MSG
440                 fi
441         else
442                 fail
443                 cat << END_OF_MSG
444 Installation of grant tables FAILED!
445
446 The initialization SQL script was preserved at $MYSQL_DATA_DIR/mysql-init.sql
447
448 Examine the logs in /var/log/mysql for more information.  You can
449 also try to start the mysqld daemon with:
450
451 /usr/sbin/mysqld --skip-grant &
452
453 You can use the command line tool mysql to connect to the mysql
454 database and look at the grant tables:
455
456 shell> mysql -u mysql mysql
457 mysql> show tables
458
459 Try 'mysqld --help' if you have problems with paths. Setting on
460 logging in /etc/mysqld.conf gives you a log in /var/log/mysql/log that
461 may be helpful. The latest information about MySQL is available on the
462 web at http://www.mysql.com/.
463
464 Please check PLD Linux ftp site for newer versions of this package.
465
466 Please consult the MySQL manual section: 'Problems running
467 mysql_install_db', and the manual section that describes problems on
468 your OS.  Another information source is the MySQL email archive.
469 Please check all of the above before mailing us!  And if you do mail
470 us, you MUST use the mysqlbug script!
471
472 END_OF_MSG
473                 exit 1
474         fi
475 }
476
477 #
478 # End of useful functions.
479 #
480
481 start() {
482         if [ ! -f $MYSQL_ERRLOG ]; then
483                 touch $MYSQL_ERRLOG
484         fi
485         chown mysql:mysql $MYSQL_ERRLOG
486         chmod 640 $MYSQL_ERRLOG
487
488         for mysqldir in $DB_CLUSTERS; do
489                 mysqlstatus "$mysqldir" start
490                 if [ "$MYSQL_STATUS" = "running" ]; then
491                         msg_already_running "MySQL $mysqldir"
492                 else
493                         mysqlstart "$mysqldir"
494                 fi
495         done
496         mysqlsubsys
497 }
498
499 stop() {
500         for mysqldir in $DB_CLUSTERS; do
501                 mysqlstatus "$mysqldir" stop
502                 if [ "$MYSQL_STATUS" = "not running" ]; then
503                         msg_not_running "MySQL $mysqldir"
504                 else
505                         mysqlstop "$mysqldir"
506                 fi
507         done
508         mysqlsubsys
509 }
510
511 RETVAL=0
512 case "$action" in
513   start)
514         start
515         ;;
516   stop)
517         stop
518         ;;
519   status)
520         for mysqldir in $DB_CLUSTERS; do
521                 mysqlstatus "$mysqldir"
522                 if [ "$MYSQL_STATUS" = "running" ]; then
523                         show "MySQL cluster %s, PID %s" "$mysqldir" "$MYSQL_PID"
524                         pids="$pids/$MYSQL_PID/"
525                         progress "$MYSQL_STATUS"
526                 else
527                         show "MySQL cluster %s" "$mysqldir"
528                         progress "$MYSQL_STATUS" "$CFAIL"
529                 fi
530                 echo
531         done
532
533         for pid in $(/sbin/pidof mysqld); do
534                 if [[ $pids != */$pid/* ]]; then
535                         running="$running $pid"
536                 fi
537         done
538
539         if [ $# -gt 1 -a "$running" ]; then
540                 nls "Warning: MySQL Daemon processes not under clusters.conf control:"
541                 # see if we can display their status
542                 for pid in $running; do
543                         datadir=$(cat /proc/$pid/cmdline | tr '\0' '\n' | fgrep -- --datadir=)
544                         datadir=${datadir#--datadir=} # strip --datadir
545                         mysqldir=${datadir%/mysqldb/db} # strip /mysqldb/db
546                         mysqlstatus "$mysqldir"
547                         if [ "$MYSQL_STATUS" = "running" ]; then
548                                 show "MySQL cluster %s, PID %s" "$mysqldir" "$pid"
549                                 progress "$MYSQL_STATUS"
550                         else
551                                 show "MySQL cluster %s" "$mysqldir"
552                                 progress "$MYSQL_STATUS" "$CFAIL"
553                         fi
554                         echo
555                 done
556         fi
557         ;;
558   restart|force-reload)
559         stop
560         start
561         ;;
562   init)
563         for mysqldir in $DB_CLUSTERS; do
564                 mysqlinit "$mysqldir"
565         done
566         exit $?
567         ;;
568   flush-logs)
569         for mysqldir in $DB_CLUSTERS; do
570             mysqlgetconfig "$mysqldir"
571                 # just if mysqld is really running
572                 if /usr/bin/mysqladmin --defaults-file="$MYSQL_CONFIG" --socket="$MYSQL_SOCKET" ping >/dev/null 2>&1; then
573                         /usr/bin/mysqladmin --defaults-file="$MYSQL_CONFIG" --socket="$MYSQL_SOCKET" flush-logs
574                 fi
575         done
576         ;;
577   *)
578         msg_usage "$0 {start|stop|init|restart|force-reload|status}"
579         exit 3
580 esac
581
582 exit $RETVAL
This page took 0.070742 seconds and 4 git commands to generate.