#!/bin/bash die() { echo "$1" exit 1 } # Read options from config file read_config() { # Initial settings MYSQLVER="$(echo @MYSQLVER@ | sed 's|\.[0-9]\+$||')" mysql_daemon_user=mysql mysql_daemon_group=mysql if [[ -z "$INSTANCE" || "x$INSTANCE" = "xdefault" ]]; then datadir=/var/lib/mysql socket="/var/run/mysql/mysql.sock" else datadir="/var/lib/mysql-$INSTANCE" socket="/var/run/mysql/mysql.${INSTANCE}.sock" fi # Read options - important for multi setup if [[ -n "$INSTANCE" && "x$INSTANCE" != "xdefault" ]]; then opts="$(/usr/bin/my_print_defaults mysqld mysqld_multi "$INSTANCE")" tmp_opts="$opts" config="/etc/my${INSTANCE}.cnf" else opts="$(/usr/bin/my_print_defaults mysqld)" tmp_opts="$opts" config="/etc/my.cnf" fi # Update local variables according to the settings from config for arg in $tmp_opts; do case "$arg" in --basedir=*) basedir="$(echo "$arg" | sed -e 's/^[^=]*=//')" ;; --socket=*) socket="$(echo "$arg" | sed -e 's/^[^=]*=//')" ;; --datadir=*) datadir="$(echo "$arg" | sed -e 's/^[^=]*=//')" ;; --user=*) mysql_daemon_user="$(echo "$arg" | sed -e 's/^[^=]*=//')" ;; esac done } # Create new empty database if needed mysql_install() { if [[ ! -d "$datadir/mysql" ]]; then echo "Creating MySQL privilege database... " mysql_install_db --user="$mysql_daemon_user" --datadir="$datadir" || \ die "Creation of MySQL databse in $datadir failed" echo -n "$MYSQLVER" > "$datadir"/mysql_upgrade_info fi } # Upgrade database if needed mysql_upgrade() { # Run mysql_upgrade on every package install/upgrade. Not always # necessary, but doesn't do any harm. if [[ -f "$datadir/.run-mysql_upgrade" ]]; then echo "Checking MySQL configuration for obsolete options..." sed -i -e 's|^\([[:blank:]]*\)skip-locking|\1skip-external-locking|' \ -e 's|^\([[:blank:]]*skip-federated\)|#\1|' /etc/my.cnf # instead of running mysqld --bootstrap, which wouldn't allow # us to run mysql_upgrade, we start a full-featured server with # --skip-grant-tables and restict access to it by unix # permissions of the named socket echo "Trying to run upgrade of MySQL databases..." # Check whether upgrade process is not already running protected="$(cat "/var/run/mysql/protecteddir.$INSTANCE" 2> /dev/null)" if [[ -n "$protected" && -d "$protected" ]]; then pid="$(cat "$protected/mysqld.pid" 2> /dev/null)" if [[ "$pid" && -d "/proc/$pid" ]] && [[ $(readlink "/proc/$pid/exe" | grep -q "mysql") ]]; then die "Another upgrade in already in progress!" else echo "Stale files from previous upgrade detected, cleaned them up" rm -rf "$protected" rm -f "/var/run/mysql/protecteddir.$INSTANCE" fi fi protected="$(mktemp -d -p /var/tmp mysql-protected.XXXXXX | tee "/var/run/mysql/protecteddir.$INSTANCE")" [ -n "$protected" ] || die "Can't create a tmp dir '$protected'" # Create a secure tmp dir chown --no-dereference "$mysql_daemon_user:$mysql_daemon_group" "$protected" || die "Failed to set group/user to '$protected'" chmod 0700 "$protected" || die "Failed to set permissions to '$protected'" # Run protected MySQL accessible only though socket in our directory echo "Running protected MySQL... " /usr/sbin/mysqld \ --defaults-file="$config" \ --user="$mysql_daemon_user" \ --skip-networking \ --skip-grant-tables \ --log-error="$protected/log_upgrade_run" \ --socket="$protected/mysql.sock" \ --pid-file="$protected/mysqld.pid" & mysql_wait "$protected/mysql.sock" || die "MySQL didn't start, can't continue" # Run upgrade itself echo "Running upgrade itself..." echo "It will do some chek first and report all errors and tries to correct them" echo if /usr/bin/mysql_upgrade --no-defaults --force --socket="$protected/mysql.sock"; then echo "Everything upgraded successfully" up_ok="" rm -f "$datadir/.run-mysql_upgrade" [[ $(grep -q "^$MYSQLVER" "$datadir/mysql_upgrade_info" 2> /dev/null) ]] || \ echo -n "$MYSQLVER" > "$datadir/mysql_upgrade_info" else echo "Upgrade failed" up_ok="false" fi # Shut down MySQL echo "Shuting down protected MySQL" kill "$(cat "$protected/mysqld.pid")" for i in {1..30}; do /usr/bin/mysqladmin --socket="$protected/mysql.sock" ping > /dev/null 2>&1 || break done /usr/bin/mysqladmin --socket="$protected/mysql.sock" ping > /dev/null 2>&1 && kill -9 "$(cat "$protected/mysqld.pid")" # Cleanup echo "Final cleanup" if [[ -z "$up_ok" ]]; then rm -rf "$protected" "/var/run/mysql/protecteddir.$INSTANCE" else die "Something failed during upgrade, please check logs" fi fi } mysql_wait() { [[ -z "$1" ]] || socket="$1" echo "Waiting for MySQL to start" for i in {1..60}; do /usr/bin/mysqladmin --socket="$socket" ping > /dev/null 2>&1 && break sleep 1 done if /usr/bin/mysqladmin --socket="$socket" ping > /dev/null 2>&1; then echo "MySQL is alive" return 0 else echo "MySQL is still dead" return 1 fi } mysql_start() { exec /usr/sbin/mysqld \ --defaults-file="$config" \ --user="$mysql_daemon_user" } # We rely on output in english at some points LC_ALL=C INSTANCE="$2" read_config mkdir -p /var/run/mysql chown --no-dereference "$mysql_daemon_user:$mysql_daemon_group" /var/run/mysql case "$1" in install) mysql_install ;; upgrade) mysql_upgrade ;; start) mysql_start ;; wait) mysql_wait ;; *) echo "Supported commands are:" echo " install - creates empty database if needed" echo " upgrade - tries to migrate data to newer version if needed" echo " start - tries to start instance" echo " wait - waits till instance is pingable" echo "All commands can take extra argument which is group from 'mysqld_multi' you want to work with" ;; esac