1 #!/bin/sh 2 # Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB 3 # This file is public domain and comes with NO WARRANTY of any kind 4 5 # MySQL daemon start/stop script. 6 7 # Usually this is put in /etc/init.d (at least on machines SYSV R4 based 8 # systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql. 9 # When this is done the mysql server will be started when the machine is 10 # started and shut down when the systems goes down. 11 12 # Comments to support chkconfig on RedHat Linux 13 # chkconfig: 2345 64 36 14 # description: A very fast and reliable SQL database engine. 15 16 # Comments to support LSB init script conventions 17 ### BEGIN INIT INFO 18 # Provides: mysql 19 # Required-Start: $local_fs $network $remote_fs 20 # Should-Start: ypbind nscd ldap ntpd xntpd 21 # Required-Stop: $local_fs $network $remote_fs 22 # Default-Start: 2 3 4 5 23 # Default-Stop: 0 1 6 24 # Short-Description: start and stop MySQL 25 # Description: MySQL is a very fast and reliable SQL database engine. 26 ### END INIT INFO 27 28 # If you install MySQL on some other places than /usr, then you 29 # have to do one of the following things for this script to work: 30 # 31 # - Run this script from within the MySQL installation directory 32 # - Create a /etc/my.cnf file with the following information: 33 # [mysqld] 34 # basedir=<path-to-mysql-installation-directory> 35 # - Add the above to any other configuration file (for example ~/.my.ini) 36 # and copy my_print_defaults to /usr/bin 37 # - Add the path to the mysql-installation-directory to the basedir variable 38 # below. 39 # 40 # If you want to affect other MySQL variables, you should make your changes 41 # in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files. 42 43 # If you change base dir, you must also change datadir. These may get 44 # overwritten by settings in the MySQL configuration files. 45 46 basedir= #mysql的安装目录 47 datadir= #数据存储路径 48 49 # Default value, in seconds, afterwhich the script should timeout waiting 50 # for server start. 51 # Value here is overriden by value in my.cnf. 52 # 0 means don't wait at all 53 # Negative numbers mean to wait indefinitely 54 service_startup_timeout=900 55 56 # Lock directory for RedHat / SuSE. 57 lockdir='/var/lock/subsys' #mysql进程锁 58 lock_file_path="$lockdir/mysql" 59 60 # The following variables are only set for letting mysql.server find things. 61 62 # Set some defaults 63 mysqld_pid_file_path= 64 if test -z "$basedir" #依次确定$basedir,$datadir,$bindir等路径 65 then 66 basedir=/usr 67 bindir=/usr/bin 68 if test -z "$datadir" 69 then 70 datadir=/var/lib/mysql 71 fi 72 sbindir=/usr/sbin 73 libexecdir=/usr/sbin 74 else 75 bindir="$basedir/bin" 76 if test -z "$datadir" 77 then 78 datadir="$basedir/data" 79 fi 80 sbindir="$basedir/sbin" 81 libexecdir="$basedir/libexec" 82 fi 83 84 # datadir_set is used to determine if datadir was set (and so should be 85 # *not* set inside of the --basedir= handler.) 86 datadir_set= 87 88 # 89 # Use LSB init script functions for printing messages, if possible 90 # 91 lsb_functions="/lib/lsb/init-functions" #linux系统脚本,包含打印log函数 92 if test -f $lsb_functions ; then #如果存在改文件,将这些函数导入该脚本 93 . $lsb_functions 94 else #否则使用自定义信息 95 log_success_msg() 96 { 97 echo " SUCCESS! $@" 98 } 99 log_failure_msg() 100 { 101 echo " ERROR! $@" 102 } 103 fi 104 105 PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin" #添加$basrdir到系统环境变量 106 export PATH 107 108 mode=$1 # start or Stop #传入启动脚本的第1个参数 109 110 [ $# -ge 1 ] && shift #如果参数个数大于等于1个,shift删掉第一个参数,将剩余参数传给$other_args 111 112 113 other_args="$*" # uncommon, but needed when called from an RPM upgrade action 114 # Expected: "--skip-networking --skip-grant-tables" 115 # They are not checked here, intentionally, as it is the resposibility 116 # of the "spec" file author to give correct arguments only. 117 118 case `echo "testing\c"`,`echo -n testing` #echo_c和echo_n的定义;\c不加换行符,-n不换行 119 *c*,-n*) echo_n= echo_c= ;; 120 *c*,*) echo_n=-n echo_c= ;; 121 *) echo_n= echo_c='\c' ;; 122 esac 123 124 125 parse_server_arguments() { #该函数将my_print_defaults 命令分析出得参数赋值给相应的变量 126 for arg do 127 case "$arg" in 128 --basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'` #利用正则表达式获取 129 bindir="$basedir/bin" 130 if test -z "$datadir_set"; then 131 datadir="$basedir/data" 132 fi 133 sbindir="$basedir/sbin" 134 libexecdir="$basedir/libexec" 135 ;; 136 --datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'` 137 datadir_set=1 138 ;; 139 --pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; 140 --service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; 141 esac 142 done 143 } 144 145 146 147 wait_for_pid () { #该函数在启动和停止mysql服务时用于等待pid的生成 148 verb="$1" # created | removed 149 pid="$2" # process ID of the program operating on the pid-file 150 pid_file_path="$3" # path to the PID file. 151 152 i=0 153 avoid_race_condition="by checking again" 154 155 while test $i -ne $service_startup_timeout ; do 156 157 case "$verb" in #处理第1个参数,created或removed 158 'created') 159 # wait for a PID-file to pop into existence. 160 test -s "$pid_file_path" && i='' && break 161 ;; 162 'removed') 163 # wait for this PID-file to disappear 164 test ! -s "$pid_file_path" && i='' && break 165 ;; 166 *) 167 echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path" 168 exit 1 169 ;; 170 esac 171 172 # if server isn't running, then pid-file will never be updated 173 if test -n "$pid"; then #如果pid非空 174 if kill -0 "$pid" 2>/dev/null; then #kill -0发送一个无效信号,可检查进程是否存在,存在返回0,反之则1 175 : # the server still runs 176 else 177 # The server may have exited between the last pid-file check and now. 178 if test -n "$avoid_race_condition"; then 179 avoid_race_condition="" 180 continue # Check again. 181 fi 182 183 # there's nothing that will affect the file. 184 log_failure_msg "The server quit without updating PID file ($pid_file_path)." 185 return 1 # not waiting any more. 186 fi 187 fi 188 189 echo $echo_n ".$echo_c" 190 i=`expr $i + 1` 191 sleep 1 #睡眠1秒 192 193 done 194 195 if test -z "$i" ; then #如果i长度为0 196 log_success_msg 197 return 0 198 else 199 log_failure_msg 200 return 1 201 fi 202 } 203 204 205 # Get arguments from the my.cnf file, 206 # the only group, which is read from now on is [mysqld] 207 if test -x ./bin/my_print_defaults #找到print_defaults的路径 208 then 209 print_defaults="./bin/my_print_defaults" 210 elif test -x $bindir/my_print_defaults 211 then 212 print_defaults="$bindir/my_print_defaults" 213 elif test -x $bindir/mysql_print_defaults 214 then 215 print_defaults="$bindir/mysql_print_defaults" 216 else 217 # Try to find basedir in /etc/my.cnf 218 conf=/etc/my.cnf 219 print_defaults= 220 if test -r $conf #如果可读,从配置文件$conf读取 221 then 222 subpat='^[^=]*basedir[^=]*=\(.*\)$' 223 dirs=`sed -e "/$subpat/!d" -e 's//\1/' $conf` 224 for d in $dirs 225 do 226 d=`echo $d | sed -e 's/[ ]//g'` 227 if test -x "$d/bin/my_print_defaults" 228 then 229 print_defaults="$d/bin/my_print_defaults" 230 break 231 fi 232 if test -x "$d/bin/mysql_print_defaults" 233 then 234 print_defaults="$d/bin/mysql_print_defaults" 235 break 236 fi 237 done 238 fi 239 240 # Hope it's in the PATH ... but I doubt it 241 test -z "$print_defaults" && print_defaults="my_print_defaults" #还是不行,就用my_print_defaults 242 fi 243 244 # 245 # Read defaults file from 'basedir'. If there is no defaults file there 246 # check if it's in the old (depricated) place (datadir) and read it from there 247 # 248 249 #配置文件的目录,先从basedir读取,不行再读取datadir的 250 extra_args="" 251 if test -r "$basedir/my.cnf" 252 then 253 extra_args="-e $basedir/my.cnf" 254 else 255 if test -r "$datadir/my.cnf" 256 then 257 extra_args="-e $datadir/my.cnf" 258 fi 259 fi 260 261 #使用parse_server_arguments函数和my_print_defaults 从my.cnf 中获取相应的参数并付给相应的变量 262 parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server` 263 264 # 265 # Set pid file if not given 266 #指定mysql启动时进程文件的位置 267 if test -z "$mysqld_pid_file_path" 268 then 269 mysqld_pid_file_path=$datadir/`hostname`.pid 270 else 271 case "$mysqld_pid_file_path" in 272 /* ) ;; 273 * ) mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;; 274 esac 275 fi 276 277 case "$mode" in 278 'start') 279 # Start daemon 280 281 # Safeguard (relative paths, core dumps..) 282 cd $basedir 283 284 echo $echo_n "Starting MySQL" 285 if test -x $bindir/mysqld_safe #如果mysqld_safe存在且可执行 286 then 287 # Give extra arguments to mysqld with the my.cnf file. This script 288 # may be overwritten at next upgrade. 289 #关键语句,启动mysqld_safe,传入3个参数:datadir,pid-file,other_args;将输出丢弃到系统黑洞/dev/null 290 $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null 2>&1 & 291 wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$? 292 293 # Make lock for RedHat / SuSE #mysql锁的检测和创建 294 if test -w "$lockdir" #如果存在且可写 295 then 296 touch "$lock_file_path" 297 fi 298 299 exit $return_value 300 else 301 log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)" 302 fi 303 ;; 304 305 'stop') 306 # Stop daemon. We use a signal here to avoid having to know the 307 # root password. 308 309 if test -s "$mysqld_pid_file_path" #如果非空 310 then 311 mysqld_pid=`cat "$mysqld_pid_file_path"` #获取mysqld进程 312 313 if (kill -0 $mysqld_pid 2>/dev/null) 314 then 315 echo $echo_n "Shutting down MySQL" 316 kill $mysqld_pid #杀死 317 # mysqld should remove the pid file when it exits, so wait for it. 318 wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$? 319 else 320 log_failure_msg "MySQL server process #$mysqld_pid is not running!" 321 rm "$mysqld_pid_file_path" 322 fi 323 324 # Delete lock for RedHat / SuSE 325 if test -f "$lock_file_path" #如果存在锁,需要移除 326 then 327 rm -f "$lock_file_path" 328 fi 329 exit $return_value 330 else 331 log_failure_msg "MySQL server PID file could not be found!" 332 fi 333 ;; 334 335 'restart') 336 # Stop the service and regardless of whether it was #重启mysql 337 # running or not, start it again. 338 if $0 stop $other_args; then 339 $0 start $other_args 340 else 341 log_failure_msg "Failed to stop running server, so refusing to try to start." 342 exit 1 343 fi 344 ;; 345 346 'reload'|'force-reload') #重载mysql 347 if test -s "$mysqld_pid_file_path" ; then 348 read mysqld_pid < "$mysqld_pid_file_path" 349 kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL" 350 touch "$mysqld_pid_file_path" 351 else 352 log_failure_msg "MySQL PID file could not be found!" 353 exit 1 354 fi 355 ;; 356 'status') 357 # First, check to see if pid file exists #mysql的状态 358 if test -s "$mysqld_pid_file_path" ; then 359 read mysqld_pid < "$mysqld_pid_file_path" 360 if kill -0 $mysqld_pid 2>/dev/null ; then 361 log_success_msg "MySQL running ($mysqld_pid)" 362 exit 0 363 else 364 log_failure_msg "MySQL is not running, but PID file exists" 365 exit 1 366 fi 367 else 368 # Try to find appropriate mysqld process 369 mysqld_pid=`pidof $libexecdir/mysqld` 370 371 # test if multiple pids exist 372 pid_count=`echo $mysqld_pid | wc -w` 373 if test $pid_count -gt 1 ; then 374 log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)" 375 exit 5 376 elif test -z $mysqld_pid ; then 377 if test -f "$lock_file_path" ; then 378 log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists" 379 exit 2 380 fi 381 log_failure_msg "MySQL is not running" 382 exit 3 383 else 384 log_failure_msg "MySQL is running but PID file could not be found" 385 exit 4 386 fi 387 fi 388 ;; 389 *) 390 # usage #输出用法的提示 391 basename=`basename "$0"` 392 echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL server options ]" 393 exit 1 394 ;; 395 esac 396 397 exit 0