永泰城乡建设网站,足球比赛直播app,广州企业网站建设电话,弓长岭网站建设#!/bin/sh# 一些状态变量的定义KILL_MYSQLD1; # 试图kill多余的mysqld_safe程序#xff0c;1表示需要killMYSQLD# mysqld二进制可执行文件的名称niceness0# 进程的调度优先级标识# 下面的变量主要用于标识不使用错误日志和sysloglogginginit # 日志记录状态#xff0c;init代…#!/bin/sh# 一些状态变量的定义KILL_MYSQLD1; # 试图kill多余的mysqld_safe程序1表示需要killMYSQLD# mysqld二进制可执行文件的名称niceness0# 进程的调度优先级标识# 下面的变量主要用于标识不使用错误日志和sysloglogginginit # 日志记录状态init代表初始化want_syslog0# 标识是否要使用syslogsyslog_tagusermysql # --user选项值pid_file# pid文件的路径err_log# 错误日志的路径# 这两个都是定义的syslog中标志位在后面需要写入日志到syslog中时使用syslog_tag_mysqldmysqldsyslog_tag_mysqld_safemysqld_safetrap 1 2 3 15# 不允许程序在终端上被人打断(包括挂起中断退出系统终止的情形)umask007# 默认权限770其他组用户对该程序创建的文件没有任何权限# defaults变量记载使用的配置文件的信息defaultscase $1 in--no-defaults|--defaults-file*|--defaults-extra-file*)defaults$1; shift;;esac# usage()函数使用--help选项时输出的使用帮助信息usage () {cat Usage: $0[OPTIONS]--no-defaults Dont read the system defaults file--defaults-fileFILE Use the specified defaults file--defaults-extra-fileFILE Also use defaults from the specified file--ledirDIRECTORY Look for mysqld inthe specified directory--open-files-limitLIMIT Limit the number of open files--core-file-sizeLIMIT Limit core files to the specified size--timezoneTZ Set the system timezone--mysqldFILE Use the specified fileas mysqld--mysqld-versionVERSION Use mysqld-VERSIONas mysqld--niceNICE Set the scheduling priority of mysqld--skip-kill-mysqld Dont try to kill stray mysqld processes--syslog Log messages to syslog with logger--skip-syslog Log messages to error log (default)--syslog-tagTAG Pass -t mysqld-TAG to loggerAll other options are passed to the mysqld program.EOFexit1}# my_which的作用相当于which通过检索$PATH中的路径打印出命令的全路径# 这个函数就在后面一个地方用到了就是my_which logger意思等同于转换logger为/usr/bin/loggermy_which (){save_ifs${IFS-UNSET}# 保存当前的内建分隔符用于后面重置IFSIFS: # 使用 来分割PATH中的路径ret0for file # 这种写法等同于for file in *dofor dir in$PATHdoif [ -f $dir/$file]thenecho $dir/$filecontinue2 # continue 第 2层, 这里就是跳出外层循环了fidoneret1# signal an errorbreakdone# 将设置过的IFS重置回去if [ $save_ifs UNSET ]thenunset IFSelseIFS$save_ifsfireturn $ret # Success}# 日志输出函数这是个原型后面被log_error和log_notice函数引用log_generic () {# priority 代表日志信息的分类从后面的两个函数可知有daemon.error和daemon.notice两种类别priority$1shift# 日志中记录的msg前缀格式 时间mysqld_safe 类似于系统日志的记录格式msgdate %y%m%d %H:%M:%S mysqld_safe $*echo $msgcase $logging ininit) ;; # 初始化状态时只在命令行输出msg信息不记录日志file) echo $msg $err_log;; # 记录到err_log中syslog) logger-t $syslog_tag_mysqld_safe -p $priority $*;; # 使用logger记录到系统日志中*)echo Internal program error (non-fatal):\unknown logging method $logging 2;;esac}# 下面两个函数是对log_generic函数中不同分类的引用log_error () {log_generic daemon.error$ 2}log_notice () {log_generic daemon.notice$}# 后面就是用它启动的mysqld通过logging变量区分记录日志的类型分错误日志和系统日志syslog两种# 最后的eval命令会解析 $cmd 中的值并执行命令eval_log_error () {cmd$1case $logging infile) cmd$cmd shell_quote_string $err_log21;;syslog)cmd$cmd 21 | logger -t $syslog_tag_mysqld -p daemon.error;;*)echo Internal program error (non-fatal):\unknown logging method $logging 2;;esac#echo Running mysqld: [$cmd]eval$cmd}# 转义函数用于在非a-zA-Z09/_.-的特殊字符前加上一个\# sed中的\1代表引用前面\(\)中匹配的值shell_quote_string() {echo $1 | sed -e s,\([^a-zA-Z0-9/_.-]\),\\\1,g}# 该函数用于解析配置文件中的选项并赋值给相应的变量parse_arguments() {pick_argsif test $1 PICK-ARGS-FROM-ARGVthenpick_args1shiftfifor arg do# 取出参数值比如--port3306 结果为 val 3306 注意这里sed中使用来分割等同于/valecho $arg | sed -e s;--[^]*;;case $arg in# 将参数值传递给对应的变量--basedir*) MY_BASEDIR_VERSION$val;;--datadir*) DATADIR$val;;--pid-file*) pid_file$val;;--user*) user$val; SET_USER1;;# 有些值可能已经在my.cnf配置文件的[mysqld_safe]组下设置了# 某些值会被命令行上指定的选项值覆盖--log-error*) err_log$val;;--port*) mysql_tcp_port$val;;--socket*) mysql_unix_port$val;;# 接下来这几个特殊的选项在配置文件的[mysqld_safe]组中是必须设置的# 我没配置这个组所以就用不到了(使用mysqld中的默认)--core-file-size*) core_file_size$val;;--ledir*) ledir$val;;--mysqld*) MYSQLD$val;;--mysqld-version*)if test -n $valthenMYSQLDmysqld-$valelseMYSQLDmysqldfi;;--nice*) niceness$val;;--open-files-limit*) open_files$val;;--skip-kill-mysqld*) KILL_MYSQLD0;;--syslog) want_syslog1;;--skip-syslog) want_syslog0;;--syslog-tag*) syslog_tag$val;;--timezone*) TZ$val; export TZ; ;; # 生效了一下时区设置--help) usage ;; # 调用了usage函数输出帮助信息*)if test -n $pick_argsthen# 将其他命令行参数值附加到$arg的后面append_arg_to_args$argfi;;esacdone}######################################### 正式工作开始了########################################## 下面两段是在寻找基目录和mysqld所在目录## 找到/usr/local/mysql3306/share/mysql目录使用relpkgdata来记录相对路径和绝对路径# 这个grep其实应该是想判断一下share/mysql是不是显示的绝对路径不知道这么写的意义在哪里。if echo /usr/local/mysql3306/share/mysql | grep ^/usr/local/mysql3306 /dev/nullthen# 一口气用了三个替换分别为# 第一步将/usr/local/mysql3306转换为空# 第二步将/share/mysql开头的/转换为空# 第三步在share/mysql开头加上./结果即./share/mysqlrelpkgdataecho /usr/local/mysql3306/share/mysql | sed -e s,^/usr/local/mysql3306,, -e s,^/,, -e s,^,./,elserelpkgdata/usr/local/mysql3306/share/mysqlfi# 这一段都是在找mysqld文件分别判断了libexec和bin目录# 找不到就使用编译时的默认值MY_PWDpwdif test -n $MY_BASEDIR_VERSION -a -d $MY_BASEDIR_VERSIONthenif test -x $MY_BASEDIR_VERSION/libexec/mysqldthenledir$MY_BASEDIR_VERSION/libexecelseledir$MY_BASEDIR_VERSION/binfi# 这里对errmsg.sys文件进行了判断个人认为这是为了确认当前目录为一个mysql安装基目录elif test -f $relpkgdata/english/errmsg.sys -a -x $MY_PWD/bin/mysqldthenMY_BASEDIR_VERSION$MY_PWDledir$MY_PWD/binelif test -f $relpkgdata/english/errmsg.sys -a -x $MY_PWD/libexec/mysqldthenMY_BASEDIR_VERSION$MY_PWDledir$MY_PWD/libexecelseMY_BASEDIR_VERSION/usr/local/mysql3306ledir/usr/local/mysql3306/libexecfi## 接下来是找到配置文件和数据文件目录## 找到配置文件目录# 我的是放在了etc/目录下mysqld程序是会读取到的## 可以从my_print_defaults脚本中获得默认的读取my.cnf顺序如下# Default options are read from the following filesinthe given order:#/etc/my.cnf /etc/mysql/my.cnf /home/mysql/mysql_master/etc/my.cnf ~/.my.cnf# 或者可以使用strace-e open libexec/mysqld 21 | grepmy.cnf查看if test -d $MY_BASEDIR_VERSION/data/mysqlthenDATADIR$MY_BASEDIR_VERSION/dataif test -z $defaults -a -r $DATADIR/my.cnfthendefaults--defaults-extra-file$DATADIR/my.cnffi# 接下来找到数据文件的目录elif test -d $MY_BASEDIR_VERSION/var/mysqlthenDATADIR$MY_BASEDIR_VERSION/var# 找不到就用编译时指定的默认值elseDATADIR/usr/local/mysql3306/varfi# 对存在两个配置文件情况进行冲突处理if test -z $MYSQL_HOMEthenif test -r $MY_BASEDIR_VERSION/my.cnf test -r $DATADIR/my.cnfthen# 优先考虑 $MY_BASEDIR_VERSION/my.cnf 文件log_errorWARNING: Found two instances of my.cnf -$MY_BASEDIR_VERSION/my.cnf and$DATADIR/my.cnfIGNORING $DATADIR/my.cnfMYSQL_HOME$MY_BASEDIR_VERSIONelif test -r $DATADIR/my.cnfthenlog_errorWARNING: Found $DATADIR/my.cnfThe data directory is a deprecated location formy.cnf, please move it to$MY_BASEDIR_VERSION/my.cnf MYSQL_HOME$DATADIRelseMYSQL_HOME$MY_BASEDIR_VERSIONfifiexport MYSQL_HOME## 下面是使用bin/my_print_defaults读取my.cnf文件中的配置信息([mysqld] and [mysqld_safe])# 并且和命令行中传入的参数进行合并# 先是找到my_print_defaults执行文件 又是各种路径判断if test -x $MY_BASEDIR_VERSION/bin/my_print_defaultsthenprint_defaults$MY_BASEDIR_VERSION/bin/my_print_defaultselif test -x ./bin/my_print_defaultsthenprint_defaults./bin/my_print_defaultselif test -x /usr/local/mysql3306/bin/my_print_defaultsthenprint_defaults/usr/local/mysql3306/bin/my_print_defaultselif test -x /usr/local/mysql3306/bin/mysql_print_defaultsthenprint_defaults/usr/local/mysql3306/bin/mysql_print_defaultselseprint_defaultsmy_print_defaultsfi# 这个函数可以将一个指定的参数附加到$arg中(在此同时执行了转义操作)append_arg_to_args () {args$argsshell_quote_string $1}args# 这里SET_USER2是针对下面一条parse_arguments来说的# 因为如果在紧接着的parse_arugments函数中设置了--user的值那么SET_USER就会变为1表示--user以被配置# 当然如果没有读取到--user的值就是说--user没有配置那么会在后面的if结构中设置SET_USER为0# 这样在后面的判断结构中SET_USER的值 0代表没有配置--user的值1代表已经配置SET_USER2# 解析配置文件中的参数使用--loose-verbose来过滤[mysqld]和[server]组中的内容parse_arguments $print_defaults $defaults--loose-verbose mysqld serverif test $SET_USER -eq 2thenSET_USER0fi# 又对[safe_mysqld]和[mysqld_safe]组中的内容进行了过滤读取# 在我的配置文件中已经没有这两个组了估计是为兼容旧版本的需要parse_arguments $print_defaults $defaults--loose-verbose mysqld_safe safe_mysqld# 用命令行输入选项 $ 来覆盖配置文件中的选项 机智parse_arguments PICK-ARGS-FROM-ARGV $## 下面是logging工具的使用## 判断logger工具是否可用if [ $want_syslog -eq 1]thenmy_which logger /dev/null 21if [ $? -ne 0]thenlog_error--syslog requested, but no logger program found. Please ensure that logger is in your PATH, or do not specify the --syslog option to mysqld_safe.exit1fifi# 给err_log改名字。。。if [ -n $err_log -o $want_syslog -eq 0]thenif [ -n $err_log]then# 下面是为err_log添加一个.err后缀(如果现在名字没有后缀)# 如果不设置这个后缀mysqld_safe和mysqld程序会将日志写入不同的文件中# 因为在 mysqld 程序中它将识别带有.的文件名为错误日志(脚本注释上说的)# 这里的expr是识别文件名中“.”前面的字符总数量(包括.)如果没有设置后缀返回就是0了if expr $err_log : .*\.[^/]*$ /dev/nullthen:elseerr_log$err_log.errficase $err_log in/*) ;;* ) err_log$DATADIR/$err_log ;;esacelseerr_log$DATADIR//bin/hostname.errfi# 追加错误日志的位置选项append_arg_to_args --log-error$err_log# 发出错误提示不要使用syslogif [ $want_syslog -eq 1 ]thenlog_error Cant log to error log and syslog at the same time. Remove all --log-error configuration options for --syslog to take effect.fi# Log to err_log filelog_notice Logging to $err_log.loggingfiles # 正式把logging改成files 使用错误日志来记录日志# 这个分支就是使用syslog的方法了elseif [ -n $syslog_tag ]then# 设置各个syslog的使用标志位syslog_tagecho $syslog_tag | sed -e s/[^a-zA-Z0-9_-]/_/gsyslog_tag_mysqld_safe${syslog_tag_mysqld_safe}-$syslog_tagsyslog_tag_mysqld${syslog_tag_mysqld}-$syslog_tagfilog_notice Logging to syslog.loggingsyslogfi# 设置--user选项USER_OPTIONif test -w / -o $USER root # 根目录是否可写或者当前用户为rootthenif test $user ! root -o $SET_USER 1thenUSER_OPTION--user$userfi# 创建错误日志并将日志授权给指定的用户if [ $want_syslog -eq 0 ]; thentouch $err_logchown $user $err_logfi# 这里它还对当前用户做了ulimit设置包括可以打开的文件数量--open_files-limit选项if test -n $open_filesthenulimit -n $open_filesappend_arg_to_args --open-files-limit$open_filesfifisafe_mysql_unix_port{mysql_unix_port:-${MYSQL_UNIX_PORT:-/usr/local/mysql3306/tmp/mysql.sock}}# 确保 $safe_mysql_unix_port 目录是存在的mysql_unix_port_dirdirname $safe_mysql_unix_portif [ ! -d $mysql_unix_port_dir ]thenmkdir $mysql_unix_port_dirchown $user $mysql_unix_port_dirchmod 755 $mysql_unix_port_dirfi# 如果用户没有制定mysqld程序的名称这里就默认赋值为mysqldif test -z $MYSQLDthenMYSQLDmysqldfi# 下面几段分别是对 mysqld pid port文件选项的检查和设置省略100个字if test ! -x $ledir/$MYSQLDthenlog_error The file $ledir/$MYSQLDdoes not exist or is not executable. Please cd to the mysql installationdirectory and restart this script from there as follows:./bin/mysqld_safeSeehttp://dev.mysql.com/doc/mysql/en/mysqld-safe.htmlfor more informationexit 1fiif test -z $pid_filethenpid_file$DATADIR//bin/hostname.pidelsecase $pid_file in/* ) ;;* ) pid_file$DATADIR/$pid_file ;;esacfiappend_arg_to_args --pid-file$pid_fileif test -n $mysql_unix_portthenappend_arg_to_args --socket$mysql_unix_portfiif test -n $mysql_tcp_portthenappend_arg_to_args --port$mysql_tcp_portfi## 接下来是关于优先级的设置#if test $niceness -eq 0thenNOHUP_NICENESSnohupelseNOHUP_NICENESSnohup nice -$nicenessfi# 将当前的默认优先级设置为0if nohup nice /dev/null 21then# normal_niceness记载默认的调度优先级normal_nicenessnice# nohup_niceness记载使用nohup执行方式的调度优先级nohup_nicenessnohup nice 2/dev/nullnumeric_nice_values1# 这个for是为了检查$normal_niceness $nohup_niceness两个变量值的合法性for val in $normal_niceness $nohup_nicenessdocase $val in-[0-9] | -[0-9][0-9] | -[0-9][0-9][0-9] | \[0-9] | [0-9][0-9] | [0-9][0-9][0-9] );;* )numeric_nice_values0 ;;esacdone# 这个判断结构很重要# 它保证了使用nohup执行的mysqld程序在调度优先级上不会低于直接执行mysqld程序的方式if test $numeric_nice_values -eq 1thennice_value_diffexpr $nohup_niceness - $normal_nicenessif test $? -eq 0 test $nice_value_diff -gt 0 \nice --$nice_value_diff echo testing /dev/null 21then# 进入分支说明$nohup_niceness的值比$normal_niceness大即nohup执行方式调度优先级比正常执行方式低# 这是不希望看到的所以下面就人为的提升了nohup的优先级(降低niceness的值)nicenessexpr $niceness - $nice_value_diffNOHUP_NICENESSnice -$niceness nohupfifielse# 下面是测试nohup在当前系统中是否可用不可用的话就置空NOHUP_NICENESSif nohup echo testing /dev/null 21then:elseNOHUP_NICENESSfifi# 指定内核文件大小if test -n $core_file_sizethenulimit -c $core_file_sizefi## 如果已经存在一个pid文件则检查是否有已经启动的mysqld_safe进程if test -f $pid_filethenPIDcat $pid_fileif /bin/kill -0 $PID /dev/null 2 /dev/nullthenif /bin/ps wwwp $PID | grep -v grep | grep -v mysqld_safe | grep -- $MYSQLD /dev/nullthenlog_error A mysqld process already existsexit 1fifi# 下面是处理办法删除旧的pid文件并报错rm -f $pid_fileif test -f $pid_filethenlog_error Fatal error: Cant remove the pid file:$pid_filePlease remove it manually and start $0 again;mysqld daemon not startedexit 1fifi## 下面便是拼接执行语句运行了。#cmd$NOHUP_NICENESS# 检查一下命令 并进行转义操作for i in $ledir/$MYSQLD $defaults --basedir$MY_BASEDIR_VERSION \--datadir$DATADIR $USER_OPTIONdocmd$cmd shell_quote_string $idonecmd$cmd $args# Avoid nohup: ignoring input warningtest -n $NOHUP_NICENESS cmd$cmd /dev/nulllog_notice Starting $MYSQLD daemon with databases from $DATADIR# 后台循环 执行mysqldwhile truedorm -f $safe_mysql_unix_port $pid_file # 保险起见又删除了一次pid文件# 调用eval_log_error函数传入$cmd参数的值最后使用eval命令执行了启动mysqldeval_log_error $cmdif test ! -f $pid_file # 没有成功创建pid文件则退出分支thenbreakfi# mysqld_safe已经启动的处理方法保证只有一个mysqld_safe程序启动if true test $KILL_MYSQLD -eq 1then# 统计启动的mysqld进程的数目numofprocesps xaww | grep -v grep | grep $ledir/$MYSQLD\ | grep -c pid-file$pid_filelog_notice Number of processes running now: $numofprocesI1while test $I -le $numofprocesdo# 这个PROC的数据即是ps mysqld_safe程序的输出 第一个数字即为进程IDPROCps xaww | grep $ledir/$MYSQLD\ | grep -v grep | grep pid-file$pid_file | sed -n $p# 使用T来获取进程IDfor T in $PROCdobreakdone# kill掉该个mysqld_safe程序if kill -9 $Tthenlog_error $MYSQLD process hanging, pid $T - killedelsebreakfi# 每干掉一个mysqld_safe就把I加一这样没有多余的mysqld_safe时就可以跳出循环了Iexpr $I 1donefilog_notice mysqld restarteddone# 完结撒花log_notice mysqld from pid file $pid_file ended