case "$mode" in 'start') # Start daemon # Safeguard (relative paths, core dumps..) cd $basedir echo $echo_n "Starting MySQL" if test -x $bindir/mysqld_safe then # Give extra arguments to mysqld with the my.cnf file. This script # may be overwritten at next upgrade. $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null 2>&1 & wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$? # Make lock for RedHat / SuSE if test -w "$lockdir" then touch "$lock_file_path" fi exit $return_value else log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)" fi ;;
wait_for_pid函数
在利用mysqld_safe启动mysql实例后,会调用该参数
wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?
其中$!在shell中用于获取最后运行的后台Process的PID,具体在本例中,是mysqld_safe进程的pid。
因为第一个参数是created,所以会执行test -s "$pid_file_path" && i='' && break命令。
-s file 如果文件的长度不为零,则为真
该命令的意思是如果pid文件存在,则将变量i设置为空,并退出while循环。
然后执行如下判断,
if test -z "$i" ; then log_success_msg return 0 else log_failure_msg return 1 fi
如果$i为空,则打印成功日志,并退出脚本,很显然,在pid文件存在的情况���,会将变量i设置为空。
再来看看pid文件不存在的情况
首先,会判断$pid是否不为空(即if test -n "$pid")
如果不为空,则代表在执行完mysqld_safe后,已经捕捉到了该进程的pid。
在这种情况下,进一步通过kill -0 "$pid"确认该进程是否存在。
kill -0就是不发送任何信号,但是系统会进行错误检查,所以经常用来检查一个进程是否存在,当进程不存在时, kill -0 pid会返回错误
如果该进程存在,则不执行任何操作,直接跳到如下操作
echo $echo_n ".$echo_c" i=`expr $i + 1` sleep 1
将变量i加1,并sleep 1s。
然后,继续while循环,之所以这样做,是考虑到mysqld_safe已经执行,但是mysqld实例还在启动过程中,还没创建好pid文件。
一直到$1达到$service_startup_timeout定义的时长。
如果在while循环的过程中,通过kill -0 "$pid"判断到进程已经不存在了,
则会再判断一次,如果这次判断的结果依旧是pid file不存在,且进程不存在,则会执行
log_failure_msg "The server quit without updating PID file ($pid_file_path)."
这就是大名鼎鼎的“The server quit without updating PID file”的由来。
wait_for_pid () { verb="$1" # created | removed pid="$2" # process ID of the program operating on the pid-file pid_file_path="$3" # path to the PID file. i=0 avoid_race_condition="by checking again" while test $i -ne $service_startup_timeout ; do case "$verb" in 'created') # wait for a PID-file to pop into existence. test -s "$pid_file_path" && i='' && break ;; 'removed') # wait for this PID-file to disappear test ! -s "$pid_file_path" && i='' && break ;; *) echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path" exit 1 ;; esac # if server isn't running, then pid-file will never be updated if test -n "$pid"; then if kill -0 "$pid" 2>/dev/null; then : # the server still runs else # The server may have exited between the last pid-file check and now. if test -n "$avoid_race_condition"; then avoid_race_condition="" continue # Check again. fi # there's nothing that will affect the file. log_failure_msg "The server quit without updating PID file ($pid_file_path)." return 1 # not waiting any more. fi fi echo $echo_n ".$echo_c" i=`expr $i + 1` sleep 1 done if test -z "$i" ; then log_success_msg return 0 else log_failure_msg return 1 fi }
服务脚本stop选项
首先,判断pid文件的长度是否不为零。
-s file 如果文件的长度不为零,则为真
此时,会通过pid文件获取mysqld进程的pid,注意,不是mysqld_safe进程的pid
然后,判断mysqld进程是否在正常运行,
如果是,则通过kill $mysqld_pid的方式来关闭mysqld进程