#!/bin/bash # # mysqld This shell script takes care of starting and stopping # the MySQL subsystem (mysqld). # # chkconfig: 345 78 12 # description: MySQL database server. # processname: mysqld # config: /etc/my.cnf # pidfile: /var/run/mysqld/mysqld.pid # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Source subsystem configuration. [ -f /etc/sysconfig/subsys/mysqld ] && . /etc/sysconfig/subsys/mysqld #################### start of import from mysql.lib ########################### MYSQL_ITER_MAGIC_NUMBER=40 MYSQL_WAIT_MAGIC_NUMBER=3 MYSQL_SKIP_VERIFY_RUNNING="" MYSQL_SINGLE_DAEMON="1" PID_FILE=/var/run/mysqld/mysqld.pid if [ -e /usr/libexec/mysqld ]; then # mysql.org RPMs MYSQLD=/usr/libexec/mysqld elif [ -e /usr/sbin/mysqld ]; then # Redhat/Fedora RPMs MYSQLD=/usr/sbin/mysqld else # unknown MYSQLD=mysqld fi MY_TMP_FILE=/tmp/tmpmysql.$$ MY_CNF_FILE=/etc/my.cnf TMPL_MY_CNF_FILE=/etc/virtualhosting/templates/mysql/etc/my.cnf TMPL_MYSQL_SOCK_FILE=/home/virtual/FILESYSTEMTEMPLATE/.mysqlsock/mysql.sock ADMIN_SOCK_FILE=`my_print_defaults -c /etc/my.cnf.admin_appl mysqld | egrep "^--socket=" | cut -d '=' -f2` if [ x"$1" = x"admin" ]; then MY_PRINT_CNF_FILE="-c /etc/my.cnf.admin_appl" else MY_PRINT_CNF_FILE="-c /etc/my.cnf" fi function commit_tmp_change() { mv -f $MY_TMP_FILE.new $MY_TMP_FILE } function remove_socket_entry() { cat $MY_TMP_FILE | egrep -v "^[\ \t]*socket[\ \t]*=.*" > $MY_TMP_FILE.new commit_tmp_change } function remove_host_entry() { cat $MY_TMP_FILE | egrep -v "^[\ \t]*host[\ \t]*=.*" > $MY_TMP_FILE.new commit_tmp_change } function update_ini_group() { HAS_INI_GROUP=`egrep "^[\ \t]*\[$1\]" $MY_TMP_FILE` if [ x"$HAS_INI_GROUP" = x"" ]; then echo "[$1] socket=$2" >> $MY_TMP_FILE else sed '/[\ \t]*\['$1'\]/ a \ socket='$2 $MY_TMP_FILE > $MY_TMP_FILE.new commit_tmp_change fi } function update_my_cnf() { rm -f $MY_TMP_FILE cp -f $MY_CNF_FILE $MY_TMP_FILE remove_socket_entry update_ini_group mysqld $TMPL_MYSQL_SOCK_FILE update_ini_group client $TMPL_MYSQL_SOCK_FILE cp -f $MY_TMP_FILE $MY_CNF_FILE rm -f $MY_TMP_FILE } function remove_virt_hardlinks() { local SITES=`find /home/virtual -type d -maxdepth 1 | egrep "/site[0-9]+"` local SITERETVAL=$? if [ $SITERETVAL -eq 0 ]; then for site_root in $SITES do IS_MYSQL_ENABLED=`egrep '^[[:space:]]*enabled[[:space:]]*=[[:space:]]*1$' $site_root/info/current/mysql` if [ x"$IS_MYSQL_ENABLED" = x"" ]; then : else rm -f $site_root/fst/var/lib/mysql/mysql.sock fi done else /sbin/initlog -f local1 -p info \ -s "mysqld init failed to exec sitelookup" fi } function create_virt_hardlinks() { local SITES=`find /home/virtual -type d -maxdepth 1 | egrep "/site[0-9]+"` local SITERETVAL=$? if [ $SITERETVAL -eq 0 ]; then for site_root in $SITES do IS_MYSQL_ENABLED=`egrep '^[[:space:]]*enabled[[:space:]]*=[[:space:]]*1$' $site_root/info/current/mysql` if [ x"$IS_MYSQL_ENABLED" = x"" ]; then : else rm -f $site_root/fst/var/lib/mysql/mysql.sock /sbin/initlog -f local1 -p info -c "ln $TMPL_MYSQL_SOCK_FILE $site_root/fst/var/lib/mysql/mysql.sock" fi done else /sbin/initlog -f local1 -p info \ -s "mysqld init failed to exec sitelookup" fi } # Attempt telnet connection to check mysql status on port 3306 # RETURNS: 0 = up, 1 = down function check_telnet { local stat hostname=$(/bin/hostname -i) telnet 127.0.0.1 3306 > /tmp/mysqlstatus.$$ 2>&1 << "EOF" a001 LOGOUT EOF # Did we get connected string grep "Connected to" /tmp/mysqlstatus.$$ > /dev/null 2>&1 stat=$? rm /tmp/mysqlstatus.$$ return $stat } # Wait for MySQL to stop answering telnet connections. function wait_telnet { local stat=0 local cnt=0 local max=$MYSQL_ITER_MAGIC_NUMBER while [ $cnt -lt $max ]; do check_telnet if [ $? -ne 0 ]; then return 0 fi let cnt=cnt+1 sleep $MYSQL_WAIT_MAGIC_NUMBER done /sbin/initlog -n mysqld_app_init -s \ "Stopping MySQL: Still answering telnet connections..." return 1 } # Check for mysql.sock file # RETURNS: 0 = up, 1 = down function check_sock { local sock_path sock_path=`my_print_defaults $MY_PRINT_CNF_FILE mysqld | egrep "^--socket=" | cut -d '=' -f2` if [ -S $sock_path ]; then return 0 fi return 1 } # Wait for sock file to appear. function wear_sock { local stat=0 local cnt=0 local max=$MYSQL_ITER_MAGIC_NUMBER while [ $cnt -lt $max ]; do check_sock if [ $? -eq 0 ]; then return 0 fi let cnt=cnt+1 sleep $MYSQL_WAIT_MAGIC_NUMBER done /sbin/initlog -n mysqld_app_init -s \ "Stopping MySQL: Socket file still hasn't appeared..." return 1 } # Wait for sock file to disappear. function wait_sock { local stat=0 local cnt=0 local max=$MYSQL_ITER_MAGIC_NUMBER while [ $cnt -lt $max ]; do check_sock if [ $? -ne 0 ]; then return 0 fi let cnt=cnt+1 sleep $MYSQL_WAIT_MAGIC_NUMBER done /sbin/initlog -n mysqld_app_init -s \ "Stopping MySQL: Socket file is still around..." return 1 } # Check if there are any MySQL processes running # RETURNS: 0 = up, 1 = down function check_procs { # See if mysql is running based on the output of ps. mysqlproc=`ps ax -o cmd | grep ^$MYSQLD` if [ -n "$mysqlproc" ]; then return 0 else return 1 fi } # Wait for the MySQL processes to disappear function wait_procs { local stat=0 local cnt=0 local max=$MYSQL_ITER_MAGIC_NUMBER while [ $cnt -lt $max ]; do check_procs if [ $? -ne 0 ]; then return 0 fi let cnt=cnt+1 sleep $MYSQL_WAIT_MAGIC_NUMBER done /sbin/initlog -n mysqld_app_init -s \ "Stopping MySQL: Some processes are still around..." return 1 } # Verify MySQL is up function verify_running { if [ "$MYSQL_SKIP_VERIFY_RUNNING" ]; then return 0 fi local stat1 local stat2 check_telnet stat1=$? check_sock stat2=$? if [ "$stat1" != "0" ] && [ "$stat2" != "0" ] ; then return 1 elif [ "$stat1" = "0" ] && [ "$stat2" = "0" ] ; then return 0 else # This is an error condition. We received conflicting # reports as to up status of MySQL return 2 fi } ##################### end of import from mysql.lib ############################ prog="MySQL" SAFE_MYSQLD_OPTIONS="--defaults-file=/etc/my.cnf --pid-file=$PID_FILE" start(){ local sock_path touch /var/log/mysqld.log chown mysql.mysql /var/log/mysqld.log chmod 0640 /var/log/mysqld.log if [ ! -d /var/lib/mysql/mysql ] ; then action $"Initializing MySQL database: " /usr/bin/mysql_install_db ret=$? chown -R mysql.mysql /var/lib/mysql if [ $ret -ne 0 ] ; then return $ret fi fi chown mysql.mysql /var/lib/mysql chmod 0755 /var/lib/mysql update_my_cnf sock_path=`my_print_defaults $MY_PRINT_CNF_FILE mysqld | egrep "^--socket=" | cut -d '=' -f2` mkdir -p `dirname $sock_path` chown mysql:mysql `dirname $sock_path` chmod 0755 `dirname $sock_path` /usr/bin/safe_mysqld $SAFE_MYSQLD_OPTIONS >/dev/null 2>&1 & ret=$? if [ $ret -eq 0 ]; then touch /var/lock/subsys/mysqld # Wait for sock to appear wear_sock if [ $? -ne 0 ]; then # This is bad problem if sock does not appear. action $"Starting $prog: " /bin/false return 1 fi # Do a full status check # PR# 31208 # If the system was crash, mysql server start up process delay for some time. # So do the verification in a 5-loop with sleep of 1 sec. for (( i=1; $i <= 5; i++ )) do verify_running ret=$? if [ $ret -eq 0 ]; then break fi sleep 1 done if [ $ret -ne 0 ]; then action $"Starting $prog: " /bin/false return 1 fi action $"Starting $prog: " /bin/true else action $"Starting $prog: " /bin/false fi chown root.mysql /var/lib/mysql if [ x"$sock_path" != x"$ADMIN_SOCK_FILE" ]; then rm -f /var/lib/mysql/mysql.sock ln -s $TMPL_MYSQL_SOCK_FILE /var/lib/mysql/mysql.sock create_virt_hardlinks fi return $ret } stop(){ # A really paranoid, thorough, patient stop. # See PRs 20077, 23203, 25559, 25985 # MySQL doesn't appear to unlink the socket so we can't use # that as a sign that it died. # If MYSQL_SINGLE_DAEMON is not set, then we assume multiple # daemons may be running and we cannot be as thorough (cannot # use killall, cannot wait for all mysqld processes to # disappear). # Stage 1: Tell the MySQL process(es) that we wish them dead. # Stage 1.1: First try using the pid file, if it's there. if [ -f $PID_FILE ]; then /bin/kill `cat $PID_FILE 2>/dev/null` \ >/dev/null 2>&1 ret=$? if [ $ret -ne 0 ]; then /sbin/initlog -n mysqld_app_init -s \ "Stopping MySQL: Failed to kill mysqld process" fi else # We couldn't find the pid file /sbin/initlog -n mysqld_app_init -s \ "Stopping MySQL: Failed to find pid file" ret=1 fi # Stage 1.2: Try killall if we couldn't kill the single pid. if [ $ret -ne 0 ] && [ "$MYSQL_SINGLE_DAEMON" ]; then # We either couldn't find the pid file, or the kill failed # for some reason. The return code from killall doesn't # tell us what happened so assume, for now, it worked. /sbin/initlog -n mysqld_app_init -s \ "Stopping MySQL: Falling back to killall" /usr/bin/killall $MYSQLD 2>/dev/null ret=0 fi if [ $ret -ne 0 ]; then # Stage 1 failed action $"Stopping $prog: " /bin/false return $ret fi # Stage 2: Make sure MySQL stops answering telnet connections. # Stage 2.1: Wait for a while, give it a chance to shut up. wait_telnet ret=$? # Stage 2.2: If it's not shutting up, try a killall. if [ $ret -ne 0 ] && [ "$MYSQL_SINGLE_DAEMON" ]; then # If we thought that killing by pid succeeded above, then # killall might help. If we already tried that, it doesn't # hurt to try it one last time. /sbin/initlog -n mysqld_app_init -s \ "Stopping MySQL: Trying killall" /usr/bin/killall $MYSQLD 2>/dev/null # Now hope the socket disappears wait_telnet ret=$? fi if [ $ret -ne 0 ]; then # Stage 2 failed action $"Stopping $prog: " /bin/false return $ret fi # Stage 3: Make sure all MySQL processes die away. if [ "$MYSQL_SINGLE_DAEMON" ]; then wait_procs ret=$? fi if [ $ret -ne 0 ]; then # Stage 3 failed action $"Stopping $prog: " /bin/false return $ret fi # Woohooooo!!!! rm -f /var/lock/subsys/mysqld rm -f /var/lib/mysql/mysql.sock /var/lib/mysql/admin_appl/mysql.sock \ $TMPL_MYSQL_SOCK_FILE remove_virt_hardlinks action $"Stopping $prog: " /bin/true return $ret } condstart(){ verify_running || restart } restart(){ stop sleep $MYSQL_WAIT_MAGIC_NUMBER start } condrestart(){ [ -e /var/lock/subsys/mysqld ] && restart || : } reload(){ [ -e /var/lock/subsys/mysqld ] && mysqladmin reload } status_mysqld() { verify_running stat=$? if [ "$stat" = "0" ] ; then echo "mysql is running" return 0 elif [ "$stat" = "1" ] ; then echo "mysql is stopped" return 0 else echo "conflicting reports, assuming mysql is stopped" return 1 fi } admin(){ stop # sock file for admin mode is different MYSQL_ADMIN_DIR="/var/lib/mysql/admin_appl" MYSQL_SOCK_FILE="${MYSQL_ADMIN_DIR}/mysql.sock" # Make sure directory exists and has proper owners if [ ! -d $MYSQL_ADMIN_DIR ]; then mkdir -m 0700 $MYSQL_ADMIN_DIR if [ $? != 0 ]; then /sbin/initlog -s "mysqld: [warning] Failed to create directory $MYSQL_ADMIN_DIR" fi fi chown mysql:mysql $MYSQL_ADMIN_DIR # don't have to do telnet test since we are connecting via # unix domain socket MYSQL_SKIP_VERIFY_RUNNING="1" # admin mode options SAFE_MYSQLD_OPTIONS="--defaults-file=/etc/my.cnf.admin_appl --skip-grant-tables --skip-networking" # make output nicer prog="$prog""in maintenance mode" start ret=$? return $? } # See how we were called. case "$1" in start) start ;; admin) admin ;; stop) stop ;; status) status_mysqld ;; reload) reload ;; restart) restart ;; condrestart) condrestart ;; condstart) condstart ;; *) echo $"Usage: $0 {start|admin|stop|status|reload|condrestart|restart}" exit 1 esac exit $?