在初始化MySQL的过程中经常会碰到各种问题,如

  1. FATAL ERROR: Could not find ./bin/my_print_defaults
  1. ERROR: Can't create/write to file '/root/test/data/mysql/db.MYI' (Errcode: 13 - Permission denied) 

出现这些问题的原因无非是两种,

1> 没有传递合适的参数。

譬如:

[root@localhost ~]# /usr/test/mariadb-10.1.16-linux-x86_64/scripts/mysql_install_db --datadir=/usr/test/mariadb-10.1.16-linux-x86_64/ --user=mysql &

没有指定basedir,无法找到my_print_defaults命令

2> 目录对当前用户没有权限

譬如:

[root@localhost test]# /usr/test/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/scripts/mysql_install_db --basedir=/usr/test/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/ --user=mysql

没有指定datadir,默认是当前目录下的data目录。如果放到/usr下执行倒是没有问题,/root目录本身的权限是500的。对于其它用户,它是没有权限在/root目录及其子目录创建文件的。

下面对MariaDB的初始化脚本进行较为详细的解析。

首先定义初始化变量

这里面ldata即数据目录,如果在执行mysql_install_db脚本时,没有显示指定--datadir,则datadir默认在当前目录下的data。

  1. basedir=""
  2. builddir=""
  3. ldata="./data"
  4. langdir=""
  5. srcdir=""
  6.  
  7. args=""
  8. defaults=""
  9. mysqld_opt=""
  10. user=""
  11.  
  12. force=
  13. in_rpm=
  14. ip_only=
  15. cross_bootstrap=

定义usage函数

在使用mysql_install_db --help即输出的是usage函数的内容

  1. usage()
  2. {
  3. cat <<EOF
  4. Usage: $ [OPTIONS]
  5. --basedir=path The path to the MariaDB installation directory.
  6. --builddir=path If using --srcdir with out-of-directory builds, you
  7. will need to set this to the location of the build
  8. directory where built files reside.
  9. --cross-bootstrap For internal use. Used when building the MariaDB system
  10. tables on a different host than the target.
  11. --datadir=path The path to the MariaDB data directory.
  12. --defaults-extra-file=name
  13. Read this file after the global files are read.
  14. --defaults-file=name Only read default options from the given file name.
  15. --force Causes mysql_install_db to run even if DNS does not
  16. work. In that case, grant table entries that
  17. normally use hostnames will use IP addresses.
  18. --help Display this help and exit.
  19. --ldata=path The path to the MariaDB data directory. Same as
  20. --datadir.
  21. --no-defaults Don't read default options from any option file.
  22. --defaults-file=path Read only this configuration file.
  23. --rpm For internal use. This option is used by RPM files
  24. during the MariaDB installation process.
  25. --skip-name-resolve Use IP addresses rather than hostnames when creating
  26. grant table entries. This option can be useful if
  27. your DNS does not work.
  28. --srcdir=path The path to the MariaDB source directory. This option
  29. uses the compiled binaries and support files within the
  30. source tree, useful for if you don't want to install
  31. MariaDB yet and just want to create the system tables.
  32. --user=user_name The login username to use for running mysqld. Files
  33. and directories created by mysqld will be owned by this
  34. user. You must be root to use this option. By default
  35. mysqld runs using your current login name and files and
  36. directories that it creates will be owned by you.
  37.  
  38. All other options are passed to the mysqld program
  39.  
  40. EOF
  41. exit
  42. }

定义打印函数

  1. s_echo()
  2. {
  3. if test "$in_rpm" -eq -a "$cross_bootstrap" -eq
  4. then
  5. echo "$1"
  6. fi
  7. }

其中$in_rpm对应--rpm参数,$cross_bootstrap对应 --cross-bootstrap参数。

关于这两个参数的作用,可以参考上面usage函数中的说明。

在脚本执行失败时,调用的函数

  1. link_to_help()
  2. {
  3. echo
  4. echo "The latest information about mysql_install_db is available at"
  5. echo "https://mariadb.com/kb/en/installing-system-tables-mysql_install_db"
  6. }

定义参数解析函数

  1. parse_arg()
  2. {
  3. echo "$1" | sed -e 's/^[^=]*=//'
  4. }

其中s是替换,^代表行首定位符,[]代表匹配一组字符里的任意字符,*匹配0个或多个前一字符,[^ ]代表匹配不在指定范围内的字符。

这个函数实现的效果是截取“=”号后的字符。

譬如,输入的变量是--basedir=/usr/test,则输出的结果是/usr/test

定义命令行解析函数

  1. parse_arguments()
  2. {
  3. # We only need to pass arguments through to the server if we don't
  4. # handle them here. So, we collect unrecognized options (passed on
  5. # the command line) into the args variable.
  6. pick_args=
  7. if test "$1" = PICK-ARGS-FROM-ARGV
  8. then
  9. pick_args=
  10. shift
  11. fi
  12.  
  13. for arg
  14. do
  15. case "$arg" in
  16. --force) force= ;;
  17. --basedir=*) basedir=`parse_arg "$arg"` ;;
  18. --builddir=*) builddir=`parse_arg "$arg"` ;;
  19. --srcdir=*) srcdir=`parse_arg "$arg"` ;;
  20. --ldata=*|--datadir=*|--data=*) ldata=`parse_arg "$arg"` ;;
  21. --user=*)
  22. # Note that the user will be passed to mysqld so that it runs
  23. # as 'user' (crucial e.g. if log-bin=/some_other_path/
  24. # where a chown of datadir won't help)
  25. user=`parse_arg "$arg"` ;;
  26. --skip-name-resolve) ip_only= ;;
  27. --verbose) verbose= ;; # Obsolete
  28. --rpm) in_rpm= ;;
  29. --help) usage ;;
  30. --no-defaults|--defaults-file=*|--defaults-extra-file=*)
  31. defaults="$arg" ;;
  32.  
  33. --cross-bootstrap|--windows)
  34. # Used when building the MariaDB system tables on a different host than
  35. # the target. The platform-independent files that are created in
  36. # --datadir on the host can be copied to the target system.
  37. #
  38. # The most common use for this feature is in the Windows installer
  39. # which will take the files from datadir and include them as part of
  40. # the install package. See top-level 'dist-hook' make target.
  41. #
  42. # --windows is a deprecated alias
  43. cross_bootstrap= ;;
  44.  
  45. *)
  46. if test -n "$pick_args"
  47. then
  48. # This sed command makes sure that any special chars are quoted,
  49. # so the arg gets passed exactly to the server.
  50. # XXX: This is broken; true fix requires using eval and proper
  51. # quoting of every single arg ($basedir, $ldata, etc.)
  52. #args="$args "`echo "$arg" | sed -e 's,\([^a-zA-Z0-9_.-]\),\\\\\1,g'`
  53. args="$args $arg"
  54. fi
  55. ;;
  56. esac
  57. done
  58. }

其中,for arg相当于for arg in '"$@"'。

PS:

关于shell脚本中$*,$@和$#三者的区别:

脚本名称叫test.sh 传入三个参数: 1 2 3

运行test.sh 1 2 3后

$*为"1 2 3"(一起被引号包住)

$@为"1" "2" "3"(分别被包住)

$#为3(参数数量)

判断给定的文件是否存在

  1. find_in_basedir()
  2. {
  3. case "$1" in
  4. --dir)
  5. return_dir=; shift
  6. ;;
  7. esac
  8.  
  9. file=$; shift
  10.  
  11. for dir in "$@"
  12. do
  13. if test -f "$basedir/$dir/$file"
  14. then
  15. if test -n "$return_dir"
  16. then
  17. echo "$basedir/$dir"
  18. else
  19. echo "$basedir/$dir/$file"
  20. fi
  21. break
  22. fi
  23. done
  24. }

其中 test -f是判断给定的文件是否存在,test -n代表给定的变量是否为非空。

解析命令行参数

正如它注释中提到的,第一次解析的参数的目录在于得到my_print_defaults命令的路径。

  1. # Ok, let's go. We first need to parse arguments which are required by
  2. # my_print_defaults so that we can execute it first, then later re-parse
  3. # the command line to add any extra bits that we need.
  4. parse_arguments "$@"

确认my_print_defaults命令的路径

  1. #
  2. # We can now find my_print_defaults. This script supports:
  3. #
  4. # --srcdir=path pointing to compiled source tree
  5. # --basedir=path pointing to installed binary location
  6. #
  7. # or default to compiled-in locations.
  8. #
  9. if test -n "$srcdir" && test -n "$basedir"
  10. then
  11. echo "ERROR: Specify either --basedir or --srcdir, not both."
  12. link_to_help
  13. exit
  14. fi
  15. if test -n "$srcdir"
  16. then
  17. if test -z "$builddir"
  18. then
  19. builddir="$srcdir"
  20. fi
  21. print_defaults="$builddir/extra/my_print_defaults"
  22. elif test -n "$basedir"
  23. then
  24. print_defaults=`find_in_basedir my_print_defaults bin extra`
  25. if test -z "$print_defaults"
  26. then
  27. cannot_find_file my_print_defaults $basedir/bin $basedir/extra
  28. exit
  29. fi
  30. else
  31. print_defaults="./bin/my_print_defaults"
  32. fi

首先,判断srcdir和basedir是否指定,如果两者都指定的话,则会报错,在这里,srcdir指向的是源码包的编译路径,basedir指向的是二进制包的解压路径。毕竟是两种不同的安装方式,一个是源码安装,一个是二进制压缩包直接解压,两者的目录层次会不一样。

上述脚本的判断逻辑是,如果$srcdir指定了,则my_print_defaults命令位于$builddir/extra中。

如果没有指定$srcdir,而指定了$basedir,则my_print_defaults要么位于$basedir/bin中,要么位于$basedir/extra中。如果没有找到该命令,则直接报错退出脚本。

如果$srcdir和$basedir都没有指定,则my_print_defaults默认在当前目录中的bin目录下,此时,它假定你是在$basedir上执行该初始化命令的。

判断my_print_defaults对于当前用户是否有可执行权限

  1. if test ! -x "$print_defaults"
  2. then
  3. cannot_find_file "$print_defaults"
  4. exit
  5. fi

获取配置文件中[mysqld]和[mysql_install_db]区域的值

  1. # Now we can get arguments from the groups [mysqld] and [mysql_install_db]
  2. # in the my.cfg file, then re-run to merge with command line arguments.
  3. parse_arguments `"$print_defaults" $defaults --mysqld mysql_install_db`

既然能执行my_print_defaults,则可以根据该命令得到配置文件中[mysqld]和[mysql_install_db]区域的值

上面的$defaults是之前定义的--no-defaults,--defaults-file,--defaults-extra-file

譬如如果--defaults-file=/usr/local/mysql,则defaults="--defaults-file=/usr/local/mysql"。

对于下面这个命令"$print_defaults" $defaults --mysqld mysql_install_db,针对于我本机的环境,它实际上执行的是

# /usr/test/mariadb-10.1.16-linux-x86_64/bin/my_print_defaults --defaults-file=/usr/test/mariadb-10.1.16-linux-x86_64/my.cnf --mysqld mysql_install_db

--port=3308
--basedir=/usr/test/mariadb-10.1.16-linux-x86_64
--datadir=/usr/test/mariadb-10.1.16-linux-x86_64/data
--skip-external-locking
--user=mysql
--key_buffer_size=16K
--max_allowed_packet=1M
--table_open_cache=4
--sort_buffer_size=64K
--read_buffer_size=256K
--read_rnd_buffer_size=256K
--net_buffer_length=2K
--thread_stack=240K
--server-id=1

其中,--mysqld前面不用带“--”也行。

但是5.6.31 MySQL社区版的my_print_defaults只支持不带“--”的mysqld,由此可见,两者在语法方面还是有一定的差别的。

根据上面的输出的结果,则脚本中的这个命令等价于

parse_arguments --port=3308 --basedir=/usr/test/mariadb-10.1.16-linux-x86_64 --datadir=/usr/test/mariadb-10.1.16-linux-x86_64/data --skip-external-locking --user=mysql --key_buffer_size=16K --max_allowed_packet=1M --table_open_cache=4 --sort_buffer_size=64K --read_buffer_size=256K --read_rnd_buffer_size=256K --net_buffer_length=2K --thread_stack=240K --server-id=1

执行完上面这个命令后,实际上只有三个参数传递进来了,--basedir,--datadir,--user

再次执行命令解析函数

  1. parse_arguments PICK-ARGS-FROM-ARGV "$@"

这次调用的目的是

1. 因为my_print_defaults如果没有指定--defaults-file参数的话,会默认读取以下位置的配置文件

  1. /etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf

这样会导致之前设置的譬如datadir之类的变量给覆盖掉。

重新执行该命令是为了确保显式设置的参数会传递进来。

2. 捕捉命令行中传递的其它参数。

譬如执行如下命令

# /usr/test/mariadb-10.1.16-linux-x86_64/scripts/mysql_install_db --defaults-file=/usr/test/mariadb-10.1.16-linux-x86_64/my.cnf --basedir=/usr/test/mariadb-10.1.16-linux-x86_64/ 123 456 789

则args中的值为' 123 456 789'

定义初始化所需文件的路径

  1. # Configure paths to support files
  2. if test -n "$srcdir"
  3. then
  4. basedir="$builddir"
  5. bindir="$basedir/client"
  6. extra_bindir="$basedir/extra"
  7. mysqld="$basedir/sql/mysqld"
  8. langdir="$basedir/sql/share/english"
  9. pkgdatadir="$srcdir/scripts"
  10. scriptdir="$srcdir/scripts"
  11. elif test -n "$basedir"
  12. then
  13. bindir="$basedir/bin"
  14. extra_bindir="$bindir"
  15. mysqld=`find_in_basedir mysqld libexec sbin bin`
  16. if test -z "$mysqld"
  17. then
  18. cannot_find_file mysqld $basedir/libexec $basedir/sbin $basedir/bin
  19. exit
  20. fi
  21. langdir=`find_in_basedir --dir errmsg.sys share/english share/mysql/english`
  22. if test -z "$langdir"
  23. then
  24. cannot_find_file errmsg.sys $basedir/share/english $basedir/share/mysql/english
  25. exit
  26. fi
  27. pkgdatadir=`find_in_basedir --dir fill_help_tables.sql share share/mysql`
  28. if test -z "$pkgdatadir"
  29. then
  30. cannot_find_file fill_help_tables.sql $basedir/share $basedir/share/mysql
  31. exit
  32. fi
  33. scriptdir="$basedir/scripts"
  34. else
  35. basedir="."
  36. bindir="./bin"
  37. extra_bindir="$bindir"
  38. mysqld="./bin/mysqld"
  39. pkgdatadir="./share"
  40. scriptdir="./bin"
  41. fi

也是分三种情况,即指定了srcdir,指定了basedir,或者两者都没有指定。

在这里,说说第二种和第三种情况

若指定了basedir,则会定义三个路径

1> mysqld,mysqld一般会存放在如下三个路径中,$basedir/libexec/mysqld,$basedir/sbin/mysqld,$basedir/bin/mysqld

2> langdir,该路径是errmsg.sys的存放路径,该文件与mysql的错误代码有关。升级时该文件即需要更新

3> pkgdatadir,该路径存放mysql库,performance_schema库的创建脚本,不仅仅是fill_help_tables.sql。

如果没有指定srcdir和basedir,则默认将当前路径设置为basedir。

定义数据库创建脚本的路径

在上面路径确认好的情况下,进一步确认脚本是否存在,mysqld是否有可执行权限,确认errmsg.sys是否存在

  1. # Set up paths to SQL scripts required for bootstrap
  2. fill_help_tables="$pkgdatadir/fill_help_tables.sql"
  3. create_system_tables="$pkgdatadir/mysql_system_tables.sql"
  4. create_system_tables2="$pkgdatadir/mysql_performance_tables.sql"
  5. fill_system_tables="$pkgdatadir/mysql_system_tables_data.sql"
  6. maria_add_gis_sp="$pkgdatadir/maria_add_gis_sp_bootstrap.sql"
  7.  
  8. for f in "$fill_help_tables" "$create_system_tables" "$create_system_tables2" "$fill_system_tables" "$maria_add_gis_sp"
  9. do
  10. if test ! -f "$f"
  11. then
  12. cannot_find_file "$f"
  13. exit
  14. fi
  15. done
  16.  
  17. if test ! -x "$mysqld"
  18. then
  19. cannot_find_file "$mysqld"
  20. exit
  21. fi
  22.  
  23. if test -n "$langdir"
  24. then
  25. if test ! -f "$langdir/errmsg.sys"
  26. then
  27. cannot_find_file "$langdir/errmsg.sys"
  28. exit
  29. fi
  30. mysqld_opt="--lc-messages-dir=$langdir/.."
  31. else
  32. mysqld_opt="--lc-messages=en_US"
  33. fi

确认主机名以及主机名是否有效

它的判断逻辑是如果--cross-bootstrap,--rpm,--force没有显式指定的话,则查看主机名是否能被解析成ip。

首先解析的是主机名,如果没有解析成功,则解析localhost

  1. # Try to determine the hostname
  2. hostname=`hostname`
  3.  
  4. # Check if hostname is valid
  5. if test "$cross_bootstrap" -eq -a "$in_rpm" -eq -a "$force" -eq
  6. then
  7. resolved=`"$extra_bindir/resolveip" $hostname >&`
  8. if test $? -ne
  9. then
  10. resolved=`"$extra_bindir/resolveip" localhost >&`
  11. if test $? -ne
  12. then
  13. echo "Neither host '$hostname' nor 'localhost' could be looked up with"
  14. echo "'$extra_bindir/resolveip'"
  15. echo "Please configure the 'hostname' command to return a correct"
  16. echo "hostname."
  17. echo "If you want to solve this at a later stage, restart this script"
  18. echo "with the --force option"
  19. link_to_help
  20. exit
  21. fi
  22. echo "WARNING: The host '$hostname' could not be looked up with resolveip."
  23. echo "This probably means that your libc libraries are not 100 % compatible"
  24. echo "with this binary MariaDB version. The MariaDB daemon, mysqld, should work"
  25. echo "normally with the exception that host name resolving will not work."
  26. echo "This means that you should use IP addresses instead of hostnames"
  27. echo "when specifying MariaDB privileges !"
  28. fi
  29. fi

如果指定了--skip-name-resolve参数,则将主机名解析为IP

  1. if test "$ip_only" -eq
  2. then
  3. hostname=`echo "$resolved" | awk '/ /{print $6}'`
  4. fi

创建数据目录

  1. # Create database directories
  2. for dir in "$ldata" "$ldata/mysql" "$ldata/test"
  3. do
  4. if test ! -d "$dir"
  5. then
  6. if ! `mkdir -p "$dir"`
  7. then
  8. echo "Fatal error Can't create database directory '$dir'"
  9. link_to_help
  10. exit
  11. fi
  12. chmod "$dir"
  13. fi
  14. if test -n "$user"
  15. then
  16. chown $user "$dir"
  17. if test $? -ne
  18. then
  19. echo "Cannot change ownership of the database directories to the '$user'"
  20. echo "user. Check that you have the necessary permissions and try again."
  21. exit
  22. fi
  23. fi
  24. done

可以看到,会创建三个目录,datadir,以及datadir下的mysql目录和test目录,这个对应mysql库和test库。

如果目录不存在,则创建,并将目录权限设置为700,如果指定了--user参数,则将目录的属主修改为指定的用户

如果指定了--user参数,则添加到之前的参数列表中

  1. if test -n "$user"
  2. then
  3. args="$args --user=$user"
  4. fi

--cross-bootstrap参数是用于跨平台启动的,具体可以参考上面parse_arguments函数中对该参数的解释

如果指定了该参数,则会过滤初始化脚本中有关当前主机名的设置。

  1. # When doing a "cross bootstrap" install, no reference to the current
  2. # host should be added to the system tables. So we filter out any
  3. # lines which contain the current host name.
  4. if test $cross_bootstrap -eq
  5. then
  6. filter_cmd_line="sed -e '/@current_hostname/d'"
  7. else
  8. filter_cmd_line="cat"
  9. fi

配置mysqld命令行

感觉MYSQLD_BOOTSTRAP变量出现得莫名其妙,上文中也没给出任何定义

这样执行的效果是如果定义了MYSQLD_BOOTSTRAP,则$MYSQLD_BOOTSTRAP值赋给mysqld_bootstrap,如果没有定义,则$mysqld的值赋给mysqld_bootstrap

  1. # Configure mysqld command line
  2. mysqld_bootstrap="${MYSQLD_BOOTSTRAP-$mysqld}"
  3. mysqld_install_cmd_line()
  4. {
  5. "$mysqld_bootstrap" $defaults "$mysqld_opt" --bootstrap \
  6. "--basedir=$basedir" "--datadir=$ldata" --log-warnings= --enforce-storage-engine="" \
  7. $args --max_allowed_packet=8M \
  8. --net_buffer_length=16K
  9. }

若以如下方式初始化mysql

# /usr/test/mariadb-10.1.16-linux-x86_64/scripts/mysql_install_db --defaults-file=/usr/test/mariadb-10.1.16-linux-x86_64/my.cnf --basedir=/usr/test/mariadb-10.1.16-linux-x86_64/

则上面这个函数相当于

/usr/test/mariadb-10.1.16-linux-x86_64/bin/mysqld --defaults-file=/usr/test/mariadb-10.1.16-linux-x86_64/my.cnf --lc-messages-dir=/usr/test/mariadb-10.1.16-linux-x86_64/share --bootstrap --basedir=/usr/test/mariadb-10.1.16-linux-x86_64/ --datadir=/usr/test/mariadb-10.1.16-linux-x86_64/data --log-warnings=0 --enforce-storage-engine="" --user=mysql --max_allowed_packet=8M --net_buffer_length=16K

执行数据库初始化脚本

分为三部分

1> 系统表

2> fill_help_tables.sql,该文件用于生成help contents的内容

3> OpenGIS

其中,--bootstrap代表Used by mysql installation scripts。

虽然同样是执行的mysqld命令,但因为指定了--bootstrap参数,只是执行了数据库初始化脚本中的命令,并没有启动数据库。

  1. # Create the system and help tables by passing them to "mysqld --bootstrap"
  2. s_echo "Installing MariaDB/MySQL system tables in '$ldata' ..."
  3. if { echo "use mysql;"; cat "$create_system_tables" "$create_system_tables2" "$fill_system_tables"; } | eval "$filter_cmd_line" | mysqld_install_cmd_line > /dev/null
  4. then
  5. s_echo "OK"
  6. else
  7. echo
  8. echo "Installation of system tables failed! Examine the logs in"
  9. echo "$ldata for more information."
  10. echo
  11. echo "The problem could be conflicting information in an external"
  12. echo "my.cnf files. You can ignore these by doing:"
  13. echo
  14. echo " shell> $scriptdir/scripts/mysql_install_db --defaults-file=~/.my.cnf"
  15. echo
  16. echo "You can also try to start the mysqld daemon with:"
  17. echo
  18. echo " shell> $mysqld --skip-grant --general-log &"
  19. echo
  20. echo "and use the command line tool $bindir/mysql"
  21. echo "to connect to the mysql database and look at the grant tables:"
  22. echo
  23. echo " shell> $bindir/mysql -u root mysql"
  24. echo " mysql> show tables;"
  25. echo
  26. echo "Try 'mysqld --help' if you have problems with paths. Using"
  27. echo "--general-log gives you a log in $ldata that may be helpful."
  28. link_to_help
  29. echo "MariaDB is hosted on launchpad; You can find the latest source and"
  30. echo "email lists at http://launchpad.net/maria"
  31. echo
  32. echo "Please check all of the above before submitting a bug report"
  33. echo "at http://mariadb.org/jira"
  34. echo
  35. exit
  36. fi
  37.  
  38. s_echo "Filling help tables..."
  39. if { echo "use mysql;"; cat "$fill_help_tables"; } | mysqld_install_cmd_line > /dev/null
  40. then
  41. s_echo "OK"
  42. else
  43. echo
  44. echo "WARNING: HELP FILES ARE NOT COMPLETELY INSTALLED!"
  45. echo "The \"HELP\" command might not work properly."
  46. fi
  47.  
  48. s_echo "Creating OpenGIS required SP-s..."
  49. if { echo "use test;"; cat "$maria_add_gis_sp"; } | mysqld_install_cmd_line > /dev/null
  50. then
  51. s_echo "OK"
  52. else
  53. echo
  54. echo "WARNING: OPENGIS REQUIRED SP-S WERE NOT COMPLETELY INSTALLED!"
  55. echo "GIS extentions might not work properly."
  56. fi

输出相关信息

针对的是--cross-bootstrap,--srcdir,--rpm这三个参数。

  1. # Don't output verbose information if running inside bootstrap or using
  2. # --srcdir for testing. In such cases, there's no end user looking at
  3. # the screen.
  4. if test "$cross_bootstrap" -eq && test -z "$srcdir"
  5. then
  6. s_echo
  7. s_echo "To start mysqld at boot time you have to copy"
  8. s_echo "support-files/mysql.server to the right place for your system"
  9.  
  10. echo
  11. echo "PLEASE REMEMBER TO SET A PASSWORD FOR THE MariaDB root USER !"
  12. echo "To do so, start the server, then issue the following commands:"
  13. echo
  14. echo "'$bindir/mysqladmin' -u root password 'new-password'"
  15. echo "'$bindir/mysqladmin' -u root -h $hostname password 'new-password'"
  16. echo
  17. echo "Alternatively you can run:"
  18. echo "'$bindir/mysql_secure_installation'"
  19. echo
  20. echo "which will also give you the option of removing the test"
  21. echo "databases and anonymous user created by default. This is"
  22. echo "strongly recommended for production servers."
  23. echo
  24. echo "See the MariaDB Knowledgebase at http://mariadb.com/kb or the"
  25. echo "MySQL manual for more instructions."
  26.  
  27. if test "$in_rpm" -eq
  28. then
  29. echo
  30. echo "You can start the MariaDB daemon with:"
  31. echo "cd '$basedir' ; $bindir/mysqld_safe --datadir='$ldata'"
  32. echo
  33. echo "You can test the MariaDB daemon with mysql-test-run.pl"
  34. echo "cd '$basedir/mysql-test' ; perl mysql-test-run.pl"
  35. fi
  36.  
  37. echo
  38. echo "Please report any problems at http://mariadb.org/jira"
  39. echo
  40. echo "The latest information about MariaDB is available at http://mariadb.org/."
  41. echo "You can find additional information about the MySQL part at:"
  42. echo "http://dev.mysql.com"
  43. echo "Support MariaDB development by buying support/new features from MariaDB"
  44. echo "Corporation Ab. You can contact us about this at sales@mariadb.com."
  45. echo "Alternatively consider joining our community based development effort:"
  46. echo "http://mariadb.com/kb/en/contributing-to-the-mariadb-project/"
  47. echo
  48. fi
  49.  
  50. exit

总结:

一、因为MySQL社区版本以及Percona版本的mysql_install_db都是用perl写的,只有MariaDB是shell写的,个人对shell比较熟悉,所以就对MariaDB的进行分析了。毕竟,这三个版本的初始化逻辑大同小异。

二、MariaDB的初始化的流程如下(为了简化,在这里就不考虑源码编译的情况,只考虑二进制包的初始化):

1. 首先判断传递的参数中是否有basedir,如果有,则查找my_print_defaults命令所在的路径,如果没有找到,则直接报错退出脚本。

2. 如果没有传递basedir参数,则将当前目录下的bin目录设置为my_print_defaults所在的路径。

3. 判断my_print_defaults对于当前用户是否有可执行权限,如果没有,也直接报错退出。

4. 根据my_print_defaults,查看配置文件中[mysqld]和[mysql_install_db]的内容,并通过parse_arguments参数赋给对应的变量

5. 查找mysqld的路径,如果没有找到,直接退出

6. 查看errmsg.sys的路径,如果没有找到,直接退出

7. 查看初始化SQL脚本的的路径,如果没有找到,直接退出

8. 确认mysqld是否有可执行权限

9. 设置--lc-messages-dir目录的位置

10. 确认主机名并解析成IP

11. 创建数据目录,数据目录下的mysql,test目录,设置权限和属主

12. 初始化mysql

MySQL数据库初始化的正确姿态

1. 显式的指定--basedir,--datadir,--user,只需指定这三个参数,即能初始化成功。

2. 如果没有指定--datadir,这个时候会根据my_print_defaults命令来解析以下位置的配置文件,注意,后面文件的参数会覆盖前面文件的参数。

  1. /etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf

如果上述文件存在且指定了datadir,则该值会传递进来。如果没有,则默认是执行初始化命令的当前目录下的data目录

所以在初始化时,可手动指定--no-defaults参数来禁止读取默认位置的配置文件

3. 当然,--basedir也不是必需的,可以切换到二进制包的解压目录执行初始化命令,此时,也可初始化成功。

补充说明:

在MySQL 5.7中,已经不再支持mysql_install_db来初始化数据库。而是使用mysqld命令,它提供了两个参数来初始化:

--initialize:会生成一个随机密码,在初始化的输出信息中有提示:

  1. --04T12::.018485Z [Note] A temporary password is generated for root@localhost: Apwdor9rpM>C

同时也会生成到error.log中

--initialize-insecure:不会生成密码。

  1. --04T13::.497403Z [Warning] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.

尽管如此,其它参数的设置仍需遵循上面的建议。

MySQL 5.6的初始化中,如果没有显示指定--datadir,则默认是当前路径的data目录下

但在MySQL 5.7的初始化中,如果没有显示指定--datadir,则默认是/usr/local/mysql/data/下

分析MariaDB初始化脚本mysql_install_db的更多相关文章

  1. MySQL初始化脚本mysql_install_db使用简介及选项参数

    mysql_install_db是一个默认放在.../mysql/scripts的一个初始化脚本. 该脚本可以在任何装有perl的操作系统上被使用,在5.6.8之前的版本,该脚本是一个shell脚本, ...

  2. ubuntu系统安装初始化脚本

    ubuntu系统安装初始化脚本 经常安装卸载ubuntu,每次系统安装完成后要安装好多软件,一个个命令输很麻烦浪费时间,一个sh文件全搞定! 1. flashplayer下载:点击这里 2. Auda ...

  3. jeecg安装——mysql数据库创建+手动执行初始化脚本

    国产的开源项目官方文档写得那么详细,已经是很厚道了,可惜俺这种菜鸟还是会碰到各种"小"问题,做个笔记先! 1.新建数据库: CREATE DATABASE jeecg DEFAUL ...

  4. centos7 系统初始化脚本

    现在自己的本地虚拟机系统,直接安装的是centos7.2 mini版,安装完成发现好多东西都没有安装,所以写了一个简单的系统初始化脚本,让自己可以省一些力气,哈哈 人懒主要是. 下面贴出写的脚本,脚本 ...

  5. Openwrt 初始化脚本

    Openwrt 使用自己的初始化脚本系统,所有的初始化脚本位于 /etc/init.d 目录下. 任何一个初始化脚本必须包含基本的 start() 和 stop() 函数.当系统启动或用户拉起对应的进 ...

  6. 分享我自己的一个最小化安装CentOS6的初始化脚本

    在自己的虚拟机上使用的基于CentOS6的系统初始化脚本 #!/bin/bash # #Filename:system_init.sh #Description:系统安装完成后,对系统进行一些配置,以 ...

  7. SpringMVC源码分析--容器初始化(五)DispatcherServlet

    上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...

  8. SpringMVC源码分析--容器初始化(四)FrameworkServlet

    在上一篇博客SpringMVC源码分析--容器初始化(三)HttpServletBean我们介绍了HttpServletBean的init函数,其主要作用是初始化了一下SpringMVC配置文件的地址 ...

  9. SpringMVC源码分析--容器初始化(三)HttpServletBean

    在上一篇博客springMVC源码分析--容器初始化(二)DispatcherServlet中,我们队SpringMVC整体生命周期有一个简单的说明,并没有进行详细的源码分析,接下来我们会根据博客中提 ...

随机推荐

  1. C#编写windows服务

    项目要求: 数据库用有一张表,存放待下载文件的地址,服务需要轮训表将未下载的文件下载下来. 表结构如下: 过程: VS--文件-->新建项目-->windows-->windows服 ...

  2. bzoj2599: [IOI2011]Race(点分治)

    写了四五道点分治的题目了,算是比较理解点分治是什么东西了吧= = 点分治主要用来解决点对之间的问题的,比如距离为不大于K的点有多少对. 这道题要求距离等于K的点对中连接两点的最小边数. 那么其实道理是 ...

  3. MYSQL MHA

    MYSQL MHA 简介: MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于 Face ...

  4. WDM驱动加载方式理解

    当PC得知有新设备插入时,总线驱动会创建相应的物理驱动PDO,然后提示有新设备插入,这时候调用相应Driver的AddDevice方法创建功能驱动FDO 下面是一个典型的AddDevice方法 #pr ...

  5. 执行jar文件生成pdf报错,Unsupported URL <file:///home

    java -Djava.library.path=/usr/local/lib/ruby/gems/1.8/gems/sharp_office-1.0.1/ext/sigar -jar /usr/lo ...

  6. ex1-第一个程序 ”helloworld”

    代码: print("Hello world.")print("Hello again.")print("I like typing this.&qu ...

  7. 非域环境下搭建自动故障转移镜像无法将 ALTER DATABASE 命令发送到远程服务器实例的解决办法

    非域环境下搭建自动故障转移镜像无法将 ALTER DATABASE 命令发送到远程服务器实例的解决办法 环境:非域环境 因为是自动故障转移,需要加入见证,事务安全模式是,强安全FULL模式 做到最后一 ...

  8. ADO.NET Entity Framework CodeFirst 如何输出日志(EF 5.0)

    ADO.NET Entity Framework CodeFirst 如何输出日志(EF4.3) 用的EFProviderWrappers ,这个组件好久没有更新了,对于SQL执行日志的解决方案的需求 ...

  9. .net中事件引起的内存泄漏分析

    系列主题:基于消息的软件架构模型演变 在Winform和Asp.net时代,事件被大量的应用在UI和后台交互的代码中.看下面的代码: private void BindEvent() { var bt ...

  10. 一道关于Promise应用的面试题

    题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯2秒亮一次:如何让三个灯不断交替重复亮灯?(用Promse实现) 三个亮灯函数已经存在: function red(){ console.log('red') ...