Mysqld_safe start Script Source read, analyze _mysql

Source: Internet
Author: User
Tags eval socket syslog system log

A few days ago read the next Mysqld_safe script, personal feeling or harvest quite large, which detailed account of the MySQL database to start the process, including the search for MySQL related directories, parsing configuration files and finally how to invoke the MYSQLD program to start the instance and so on, has a good reference value At the same time, the script involves a lot of tricks in shell programming, such as variable resolution, sed substitution escape, process priority judgment and everywhere test structure, etc., as the Linux shell learning material is very appropriate, the following is my environment:

Database version: MySQL 5.1.45
Operating system version: Red Hat Enterprise Linux as Release 4 (Nahant Update 3)
MySQL Base directory:/usr/local/mysql3306
Configuration file directory:/usr/local/mysql3306/etc

The database is installed and the code is as follows:

#!/bin/sh # Some definitions of state variables kill_mysqld=1; # trying to kill the extra Mysqld_safe program, 1 means you need to kill mysqld= # MYSQLD binary executable name niceness=0 # process scheduling Priority identification # The following variables are used primarily to identify the use of error logs and Syslo  G Logging=init # Logging status, Init on behalf of Initialize Want_syslog=0 # identifies whether to use syslog syslog_tag= user= ' mysql ' #--user option value pid_file= # Path of the PID file # err_log= # error Log path # These are both defined in the syslog with the flag bit, which is used when you need to write to the log in the syslog syslog_tag_mysqld=mysqld Syslog_tag_mysqld_saf E=mysqld_safe Trap ' 1 2 3 15 # Do not allow the program to be interrupted on the terminal (including suspend, interrupt, exit, System termination situation) Umask 007 # Default Permissions 770, other group users do not have any permissions on the files created by the program # D  The efaults variable records the information used in the profile defaults= case "$" in--no-defaults|--defaults-file=*|--defaults-extra-file=*) defaults= "$";
shift;; ESAC # Usage () function: Use Help information for output when using--HELP option usage () {Cat <<eof usage: $ [OPTIONS]--no-defaults Don ' t read The system defaults file--defaults-file=file use the specified defaults file--defaults-extra-file=file Also use Def Aults from the specified file--ledir=directory to mysqld in the specified directorY--open-files-limit=limit Limit the number of open files--core-file-size=limit limit core files to the specified SI Ze--timezone=tz Set The system timezone--mysqld=file use the specified FILE as mysqld--mysqld-version=ve Rsion use "Mysqld-version" as mysqld--nice=nice Set The scheduling priority of Mysqld--skip-kill-mysqld N ' t try to kill stray mysqld processes--syslog log messages to syslog with ' logger '--skip-syslog log Me  Ssages to error log (default)--syslog-tag=tag pass-t "Mysqld-tag" to ' logger ' all other options are passed to the

MYSQLD program. EOF exit 1} # My_which function is equivalent to which, by retrieving the path in the $path, printing out the full path of the command # This function is used in the latter place, that is, My_which logger, meaning equivalent to conversion logger to/usr/bin /logger My_which () {save_ifs= "${ifs-unset}" # Saves the current built-in separator for later reset IFS ifs=: # use: To split paths in path ret=0 for F Ile # This is equivalent to the for file in &* does for dir in $PATH do if [f "$dir/$file"] then echo $dir/$fi
  Le  Continue 2 # Continue 2nd Floor, here's the loop out of the outer layer. Fi done Ret=1 # signal a error break done # Reset the set of IFS back to if [ "$save _ifs" = UNSET] then UNSET ifs else ifs= "$save _ifs" fi return $ret # Success} # Log output function, which is a prototype, followed by Log_error

and Log_notice Function Reference Log_generic () {# Priority represents the classification of log information, from the following two functions can be seen: Daemon.error and daemon.notice two categories priority= "" "Shift The MSG prefix format recorded in the # log: Time + Mysqld_safe, similar to the logging format of the System log msg= "' Date + '%y%m%d%h:%m:%s ' mysqld_safe $*" echo "$msg" Case $loggin                g in Init);;   # when initializing state, only msg information is output at the command line, no log file is recorded echo "$msg" >> "$err _log";; # Log to Err_log logger-t ' "$syslog _tag_mysqld_safe"-P "$priority" "$*";; # Use Logger to log in to the syslog *) echo "Internal program error (Non-fatal):" Unknown logging method ' $logging ' >&am
 P;2;; ESAC} # The following two functions are references to different classifications in the Log_generic function Log_error () {log_generic daemon.error "$@" >&2} log_notice () {Log_g Eneric daemon.notice "$@"} # behind it is the mysqld that starts with it, distinguishes the record log type by the logging variable, the wrongFalse and System log syslog two # The last eval command resolves the value in the $cmd and executes the command Eval_log_error () {cmd= "case $logging in File" cmd= "$cmd >>"
  ' shell_quote_string ' $err _log ' "2>&1";; syslog) cmd= "$cmd 2>&1 |
  Logger-t ' $syslog _tag_mysqld '-P daemon.error ';;
 * echo "Internal program error (non-fatal):" \ "Unknown logging method ' $logging '" &GT;&AMP;2;; Esac #echo "Running mysqld: [$cmd]" eval "$cmd"} # Escape function, for special characters that are not "A-Z", "A-Z", "09", '/', ' _ ', '. ', ' = ', '-', plus a "#" in the SED 1 represents a reference to a matching value in front \ (\) {echo ' shell_quote_string ' | sed-e ' s,\ ([^a-za-z0-9/_.=-]\), \\\1,g '} # This function is used to resolve the options in the configuration file and assign values to the corresponding variable Quantity Parse_arguments () {pick_args= if test "$" = PICK-ARGS-FROM-ARGV then Pick_args=1 shift fi for ARG do # fetch parameters Values, such as the--port=3306 result: val = 3306 Note the use of SED here; to split, equivalent to/val= ' echo ' $arg | Sed-e "s;--[^=]*=;;"
   ' Case ' $arg ' in # Pass the parameter value to the corresponding variable--basedir=*) my_basedir_version= "$val";;
   --datadir=*) datadir= "$val";;
   --pid-file=*) pid_file= "$val";; --user=* user= "$val";

   Set_user=1;;
   # Some values may have been set under the [Mysqld_safe] group of the MY.CNF configuration file. Some values are overwritten--log-error=* by the option values specified on the command line err_log= "$val";;
   --port=*) mysql_tcp_port= "$val";;

   --socket=*) mysql_unix_port= "$val";; # The next few special options must be set in the [Mysqld_safe] group of the configuration file # I did not configure this group, so I could not use the (default in mysqld)--core-file-size=*) core_file_size= "$val";
   ;
   --ledir=*) ledir= "$val";;
   --mysqld=*) mysqld= "$val";;
   --mysqld-version=*) If Test-n "$val" then mysqld= "mysqld-$val" Else mysqld= "mysqld" FI;;
   --nice=*) niceness= "$val";;
   --open-files-limit=*) open_files= "$val";;
   --skip-kill-mysqld*) kill_mysqld=0;;
   --syslog) want_syslog=1;;
   --skip-syslog) want_syslog=0;;
   --syslog-tag=*) syslog_tag= "$val";; --timezone=*) tz= "$val"; Export TZ;;; # takes effect. Time zone set--help) usage;; 
    # Call the usage function, output help information *) if test-n "$pick _args" then # attach additional command-line parameter values to the back of $arg "$arg"
  fi;; Esac done} ######################################## # The official work begins!! ######################################## # # The following two paragraphs are looking for the base directory and mysqld directory # # Find the/usr/local/mysql3306/share/mysql directory,
Use Relpkgdata to record relative paths and absolute paths # This grep should actually be to determine the share/mysql is not the absolute path shown, do not know what the meaning of this writing. If Echo '/usr/local/mysql3306/share/mysql ' | grep ' ^/usr/local/mysql3306 ' >/dev/null then # with three replacements, respectively: # First step: Convert/usr/local/mysql3306 to Empty # Step two: Start the/share/mysql /Convert to Empty # Step three: At the beginning of the Share/mysql Add./, the result is:./share/mysql relpkgdata= ' echo '/usr/local/mysql3306/share/mysql ' | Sed-e ' s,^/usr/local/mysql3306,, ' E ' s,^/,, ' E ' s,^,./, ' else relpkgdata= '/usr/local/mysql3306/share/mysql ' fi # This section are looking for mysqld files, respectively, to determine libexec and Bin directory # to use the compile-time default value my_pwd= ' PWD ' if Test-n ' $MY _basedir_version '-a-d ' $MY _basedir_version "Then if Test-x" $MY _basedir_version/libexec/mysqld "then ledir=" $MY _basedir_version/libexec "Else ledir=" $MY _bas Edir_version/bin "Fi # Here's a Errmsg.sys file, personally think this is to confirm the current directory for a MySQL installation base directory elif test-f" $relpkgdata "/english/errmsg.sys -a-x "$MY _pwd/bin/mysqlD "then my_basedir_version=" $MY _pwd "ledir=" $MY _pwd/bin "elif test-f" $relpkgdata "/english/errmsg.sys-a-X" $MY _pwd/li Bexec/mysqld "Then my_basedir_version=" $MY _pwd "ledir=" $MY _pwd/libexec "Else my_basedir_version="/usr/local/
mysql3306 ' ledir= '/usr/local/mysql3306/libexec ' fi # The next step is to find the configuration file and data file directory # # Find the Profile Directory # Mine is placed in the etc/directory, the MYSQLD program will read the #   # The default read MY.CNF sequence can be obtained from the My_print_defaults script, as follows # Default options are read from the following files in the given order: # /ETC/MY.CNF/ETC/MYSQL/MY.CNF/HOME/MYSQL/MYSQL_MASTER/ETC/MY.CNF ~/.MY.CNF # or you can use STRACE-E open libexec/mysqld 2> &1 | grep my.cnf View If test-d $MY _basedir_version/data/mysql then datadir= $MY _basedir_version/data if Test-z "$defaults"-A -R "$DATADIR/my.cnf" then defaults= "--defaults-extra-file= $DATADIR/my.cnf" Fi # Next locate the directory for the data file elif test-d $MY _basedir_ Version/var/mysql then datadir= $MY _basedir_version/var # can not find the default value specified at compile time else Datadir=/usr/local/mysql3306/var fi # pair exists two A configuration file is handled in conflict with the If Test-z "$MYSql_home "Then if Test-r" $MY _basedir_version/my.cnf "&& test-r" $DATADIR/my.cnf "then" priority consideration $MY _basedir_v ERSION/MY.CNF file Log_error "Warning:found two instances of my.cnf-$MY _basedir_version/my.cnf and $DATADIR/my.cnf Ring $DATADIR/my.cnf "Mysql_home= $MY _basedir_version elif test-r" $DATADIR/my.cnf "then Log_error" Warning:found $DATADIR/my.cnf The Data directory is a deprecated location for my.cnf, please move it to $MY _basedir_version/my.cnf "my Sql_home= $DATADIR Else mysql_home= $MY _basedir_version fi fi export Mysql_home # below is read bin/my_print_defaults with MY.CNF The configuration information in the ([Mysqld] and [Mysqld_safe]) # and merge with the parameters passed in to the command line # First find my_print_defaults execution file is a variety of paths to judge if Test-x "$MY _basedir_versi On/bin/my_print_defaults "Then print_defaults=" $MY _basedir_version/bin/my_print_defaults elif test-x./bin/my_
Print_defaults then print_defaults= "./bin/my_print_defaults" Elif test-x Then print_defaults= "/usr/local/mysqL3306/bin/my_print_defaults "Elif test-x/usr/local/mysql3306/bin/mysql_print_defaults then print_defaults="/usr/ Local/mysql3306/bin/mysql_print_defaults "Else print_defaults=" My_print_defaults "fi" This function can attach a specified parameter to the $arg ( An escape operation was performed at the same time) Append_arg_to_args () {args= "$args" ' Shell_quote_string '} args= # here set_user=2 is for one of the following parse_argument # for S # because if you set the--user value in the next parse_arugments function, then Set_user will be 1, which means--user to be configured # Of course, if you don't read the--user value, that means--user is not configured, Then the set_user is set to 0 # in the later if structure so that in the subsequent judgment structure, the value 0 of Set_user represents a value that is not configured--user, and 1 represents the parameters that have been configured in the Set_user=2 # resolution configuration file. 

Use--loose-verbose to filter content in [mysqld] and [Server] groups parse_arguments ' $print _defaults $defaults--loose-verbose mysqld server '
if test $SET _user-eq 2 then set_user=0 fi # and filtered the content in the [Safe_mysqld] and [Mysqld_safe] groups # There are no more than two groups in my profile, estimated to be compatible with older versions Parse_arguments ' $print _defaults $defaults--loose-verbose mysqld_safe safe_mysqld ' # Use the command-line input option $@ to overwrite the options in the configuration file wit Parse_ar Guments pick-args-from-argv "$@" # below is the use of the Logging tool # # To determine if the logger tool is available if [$waNt_syslog-eq 1] Then My_which logger >/dev/null 2>&1 if [$-ne 0] then Log_error "--syslog requested, But no ' logger ' program found.
  Please ensure that ' logger ' are in your PATH, or don't specify the--syslog option to Mysqld_safe.
Exit 1 fi Fi # change name to Err_log ... If [-N "$err _log"-O $want _syslog-eq 0] then if [-N "$err _log"] then # The following is to add a. err suffix to err_log (if the name does not have a suffix now) # If you do not set this suffix, the mysqld_safe and mysqld programs write the log in a different file # because in the MYSQLD program, it will recognize the file name with the. Error log (said on the script annotation) # Here expr is the "." In the identification file name. The total number of characters in front (including.), if no suffix is set, the return is 0 if expr "$err _log": '. *\.
   [^/]*$ ' >/dev/null then:else err_log= "$err _log". Err fi case "$err _log" in/*)
  * err_log= "$DATADIR/$err _log";; Esac else err_log= $DATADIR/'/bin/hostname '. Err Fi # Append error log location options Append_arg_to_args "--log-error= $err _log" # Make a mistake Example: Do not use the syslog if [$want _syslog-eq 1] then Log_error "Can" T log to error log and syslog in the same time. Remove all--log-error configuration options for--syslog to take effect. "
 Fi # Log to Err_log file Log_notice "Logging to ' $err _log '." Logging=files # officially changed the logging to files. Log with error log # This branch is the way to use syslog. else if [-N ' $syslog _tag] then # Set the usage standard for each syslog Chi syslog_tag= ' echo ' $syslog _tag | Sed-e ' s/[^a-za-z0-9_-]/_/g ' syslog_tag_mysqld_safe= ' ${syslog_tag_mysqld_safe}-$syslog _tag "syslog_tag_mysqld=" $
 {syslog_tag_mysqld}-$syslog _tag "fi log_notice" Logging to Syslog. " Logging=syslog fi # Set--user option user_option= "" If Test-w/o "$USER" = "root" # root directory is writable, or the current user is root then if test $use R "!=" "root"-o $SET _user = 1 then user_option= "--user= $user" FI # creates an error log and authorizes the log to the specified user if [$want _syslog-eq 0]; Then touch "$err _log" Chown $user "$err _log" fi # Here it also makes Ulimit settings for the current user, including the number of files that can be opened--open_files-limit option if Test-n "$ Open_files "then ulimit-n $open _files append_arg_to_args"--open-files-limit= $open _files "fi fi Safe_mysql_unix_po Rt={mysql_unix_port:-${mysql_unix_port:-/usr/local/mysql3306/tmp/mysql.socK}} # Ensure that the $safe _mysql_unix_port directory is present mysql_unix_port_dir= ' dirname $safe _mysql_unix_port ' if [!-D $mysql _unix_port_dir] Then mkdir $mysql _unix_port_dir chown $user $mysql _unix_port_dir chmod 755 $mysql _unix_port_dir fi # If the user does not develop a mysqld program  Name, where the default assignment is MYSQLD if Test-z "$MYSQLD" then mysqld=mysqld Fi # The following paragraphs are for the MYSQLD, PID, port file options check and settings, omit 100 words if test! -X "$ledir/$MYSQLD" then Log_error "the file $ledir/$MYSQLD does not exist or are not executable. Please CD to the MySQL installation directory and restart this script from there as follows: ./bin/mysqld_safe& Tp://dev.mysql.com/doc/mysql/en/mysqld-safe.html for more information "Exit 1 fi if test-z" $pid _file "then pid_file="
  $DATADIR/'/bin/hostname '. pid "Else case" $pid _file "in/*);;
 * pid_file= "$DATADIR/$pid _file";; Esac fi Append_arg_to_args "--pid-file= $pid _file" If Test-n "$mysql _unix_port" then Append_arg_to_args "--socket= $mysql _unix_port "fi if Test-n" $mysql _tcp_port "then append_arg_to_args "--port= $mysql _tcp_port" Fi # Next is about priority setting # if test $niceness-eq 0 Then nohup_niceness= ' NOHUP ' else nohup_ni ceness= "Nohup nice-$niceness" Fi # Set the current default priority to 0 if nohup nice >/dev/null 2>&1 then # normal_niceness Chronicle default tuning Degree priority normal_niceness= ' Nice ' # nohup_niceness records the scheduling priority using Nohup execution nohup_niceness= ' nohup nice 2>/dev/null ' numeri 
    C_nice_values=1 # This for is to check the legality of the $normal_niceness $nohup _niceness two variable values for Val $normal _niceness $nohup _niceness do Case "$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_values=0;; Esac done # This judgment structure is important # It guarantees that the MYSQLD program executed using nohup will not be less than the way to execute the MYSQLD program directly on the dispatch priority if test $numeric _nice_values-eq 1 the n nice_value_diff= ' expr $nohup _niceness-$normal _niceness ' if test $? -eq 0 && Test $nice _value_diff-gt 0 && \ Nice--$nice _value_diff echo testing >/dev/null 2>&
Amp;1 Then      # Enter the branch description the value of the $nohup_niceness is larger than the $normal_niceness, that is, the Nohup execution mode is lower than normal execution. This is not desirable, so the following artificially elevated the nohup priority (lower niceness niceness= ' expr $niceness-$nice _value_diff ' nohup_niceness= ' nice-$niceness NOHUP "fi fi Else # under The face is to test whether Nohup is available in the current system, empty nohup_niceness if nohup echo testing >/dev/null 2>&1 then:else Nohu p_niceness= "" Fi Fi # Specifies the kernel file size if test-n "$core _file_size" then ulimit-c $core _file_size fi # # If a PID file already exists, check whether There are mysqld_safe processes already started if test-f "$pid _file" then pid= ' Cat "$pid _file" ' if/bin/kill-0 $PID >/dev/null 2>/dev/nul L then if/bin/ps wwwp $PID | Grep-v "grep" | Grep-v Mysqld_safe | grep--"$MYSQLD" >/dev/null then Log_error "A MYSQLD process already exists" Exit 1 fi fi # Here's the deal: delete the old P ID file and error rm-f "$pid _file" if Test-f "$pid _file" then Log_error "Fatal error:can ' t remove the PID file: $pid _file Pl
Ease remove it manually and start $ again;
  Mysqld Daemon Not Started "Exit 1 fi fi # Below is the concatenation execution statement running. # cmd= "$NOHUP _niceness" # Check the command and escape operation for I in "$ledir/$MYSQLD" "$defaults" "--basedir= $MY _basedir_version" \ "--dat adir= $DATADIR "$USER _option" do cmd= "$cmd" ' shell_quote_string ' $i ' done cmd= ' $cmd $args ' # avoid ' nohup:ignoring Inpu T ' warning Test-n "$NOHUP _niceness" && cmd= "$cmd </dev/null" Log_notice "starting $MYSQLD daemon with Databa Ses from $DATADIR "# background loop performs mysqld while true do rm-f $safe _mysql_unix_port" $pid _file "# to insure, and to remove the PID file # call eval_l Og_error function, passing in the value of the $cmd parameter, and finally using the Eval command to perform the boot mysqld eval_log_error "$cmd" if test! -F "$pid _file" # did not successfully create the PID file, then quit the branch then break FI # Mysqld_safe The processing method that has been started to ensure that only one Mysqld_safe program starts if True && t EST $KILL _mysqld-eq 1 Then # Statistics the number of MYSQLD processes initiated numofproces= ' PS Xaww | Grep-v "grep" | grep "$ledir/$MYSQLD \>" | Grep-c "pid-file= $pid _file" "log_notice" number of processes running now: $numofproces "i=1 while Test" $I "-le" $ Numofproces "Do #" this proc data isis the output of the PS Mysqld_safe program the first number is the process ID proc= ' PS xaww | grep "$ledir/$MYSQLD \>" | Grep-v "grep" | grep "pid-file= $pid _file" | 
    Sed-n ' $p ' # uses T to get process ID for T in $PROC does break done # Kill the Mysqld_safe program if kill-9 $T then Log_error "$MYSQLD process hanging, pid $T-killed" Else break fi # I add one to every mysqld_safe, so there's no extra MYSQLD _safe can jump out of the loop i= ' expr $I + 1 ' done fi log_notice ' mysqld restarted ' do # end strewing Log_notice ' mysqld from PID file $pid _file ended "

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.