1. 程式人生 > >mysqld_safe 啟動資料庫報找不到 mysqld 啟動檔案

mysqld_safe 啟動資料庫報找不到 mysqld 啟動檔案

.版本

1)作業系統

cat /etc/issue
CentOS release 6.9 (Final)
Kernel \r on an \m

cat /proc/version
Linux version 2.6.32-696.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) ) #1 SMP Tue Mar 21 19:29:05 UTC 2017

2)mysql資料庫版本

mysql --version
mysql  Ver 14.14 Distrib 5.6.26, for linux-glibc2.5 (x86_64) using  EditLine wrapper

2. 問題描述

2.1 發現問題

   新公司資料庫全部安裝在/opt/路徑下(二進位制安裝),在這之前我是所有的資料庫都是按照官方文件部署在/usr/local目錄下的。本來覺得這不是什麼事,但是發現在/opt/下面安裝完mysql 後 使用 mysqld_safe --defaults-file=/etc/my3306.cnf & 啟動資料庫的時候確報如下錯誤(my3306.cnf 檔案中指已經指定了 basedir=/opt/mysql)

[[email protected] ~]# mysqld_safe --defaults-file=/etc/my3306.cnf &
[1] 42815
[[email protected]
~]# 180502 09:36:53 mysqld_safe Logging to '/data/mysql/mysql3306/log/error3306.log'. 180502 09:36:53 mysqld_safe The file /usr/local/mysql/bin/mysqld does not exist or is not executable. Please cd to the mysql installation directory and restart this script from there as follows: ./bin/mysqld_safe& See http://dev.mysql.com/doc/mysql/en/mysqld-safe.html for more information [1]+ Exit 1 mysqld_safe --defaults-file=/etc/my3306.cnf

##啟動的時候報找不到 /usr/local/mysql/bin/mysqld 可執行檔案,我在配置檔案中 指定了 basedir = /opt/mysql,怎麼還會去/usr/local/mysql/bin下面找mysqld,應該是去/opt/mysql/bin/下面找才對啊。

2.2 問題原因

  想要知道真正的原因,那我們就去看一下 mysqld_safe 到底是怎麼去找 mysqld 檔案,然後啟動資料庫的,下面我們擷取 mysqld_safe指令碼中 跟本問題 相關的部分程式碼(大家可以直接看自己mysqld_safe完整程式碼)

#
# First, try to find BASEDIR and ledir (where mysqld is)
#
####這部分就是 mysqld_safe 中用來判斷  basedir 的那部分程式碼


if echo '/usr/local/mysql/share' | grep '^/usr/local/mysql' > /dev/null
then
  relpkgdata=`echo '/usr/local/mysql/share' | sed -e 's,^/usr/local/mysql,,' -e 's,^/,,' -e 's,^,./,'`
else
  # pkgdatadir is not relative to prefix
  # pkgdatadir is not relative to prefix
  relpkgdata='/usr/local/mysql/share'
fi
####上面的if迴圈 最後給變數賦值為 relpkgdata='./share'


MY_PWD=`pwd`
####注意了這個 MY_PWD 變數就是問題的關鍵,這裡把當前路徑值賦值給 MY_PWD 這個變數


# Check for the directories we would expect from a binary release install
if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION"
####注意了 MY_BASEDIR_VERSION 這個變數也是個關鍵點,mysqld_safe 指令碼中的parse_arguments函式會通過啟動時指定的配置檔案和命令列引數,對該引數進行賦值,如果該引數在配置檔案和命令中都出現,則命令列中的值覆蓋配置檔案中的(其實就是把basedir賦值給該變數)。但是因為指令碼中parse_arguments函式的呼叫是在 "find BASEDIR and ledir" 這部分程式碼之後,所以,這裡的 if test -n "$MY_BASEDIR_VERSION" 為false 
then
  # BASEDIR is already overridden on command line.  Do not re-set.


  # Use BASEDIR to discover le.
  if test -x "$MY_BASEDIR_VERSION/libexec/mysqld"
  then
    ledir="$MY_BASEDIR_VERSION/libexec"
  elif test -x "$MY_BASEDIR_VERSION/sbin/mysqld"
  then
    ledir="$MY_BASEDIR_VERSION/sbin"
  else
    ledir="$MY_BASEDIR_VERSION/bin"
  fi
  ####上面的if迴圈用來在 MY_BASEDIR_VERSION 變數存在且是目錄的時候,生成相應的basedir(如上面分析因為指令碼中還未生成MY_BASEDIR_VERSION,我們也沒有在執行指令碼之前手動設定MY_BASEDIR_VERSION變數,所以指令碼不會走到該部分)
elif test -f "$relpkgdata"/english/errmsg.sys -a -x "$MY_PWD/bin/mysqld"
then
####如果MY_BASEDIR_VERSION為空,或者不是目錄,那麼執行上面的 elif判斷 "$relpkgdata"/english/errmsg.sys 是否為檔案,並且"$MY_PWD/bin/mysqld"是否為可執行檔案,如果條件成立,執行then部分(relpkgdata變數上面已經給出)
  MY_BASEDIR_VERSION="$MY_PWD"          # Where bin, share and data are
  ####這裡是指定basedir目錄
  ledir="$MY_PWD/bin"                   # Where mysqld is
  ####這裡是指定 mysqld 可執行檔案路徑
# Check for the directories we would expect from a source install
####下面的elif判斷都類似上面的分析(用來指定basedir目錄,和 mysqld 可執行檔案路徑)
elif test -f "$relpkgdata"/english/errmsg.sys -a -x "$MY_PWD/libexec/mysqld"
then
  MY_BASEDIR_VERSION="$MY_PWD"          # Where libexec, share and var are
  ledir="$MY_PWD/libexec"               # Where mysqld is
elif test -f "$relpkgdata"/english/errmsg.sys -a -x "$MY_PWD/sbin/mysqld"
then
  MY_BASEDIR_VERSION="$MY_PWD"          # Where sbin, share and var are
  ledir="$MY_PWD/sbin"                  # Where mysqld is
# Since we didn't find anything, used the compiled-in defaults
else
  MY_BASEDIR_VERSION='/usr/local/mysql'
  ledir='/usr/local/mysql/bin'
  ####最後else這部分也是關鍵,就是在前面判斷都不成立的情況下,就設定 basedir 為/usr/local/mysql,可執行檔案路徑為/usr/local/mysql/bin(這就是我執行mysqld_safe時報/usr/local/mysql/bin/mysqld 不存在的原因)
fi

    在mysqld_safe指令碼的開始部分,我們可以看到如下部分內容,也就是說,二進位制安裝如果我們的basedir沒有用預設的/usr/local/mysql,那麼我們必須在basedir 目錄下執行mysqld_safe:

# This should be executed in the MySQL base directory if you are using a
# binary installation that is not installed in its compile-time default
# location

    通過上面對mysqld_safe 中“First, try to find BASEDIR and ledir (where mysqld is)”這部分程式碼的分析,我們已經指定問題的原因了,下面總結一下:

其實程式碼中 MY_BASEDIR_VERSION(basedir) 的判斷可以分為三部分:

第一部分 通過MY_BASEDIR_VERSION變數來判斷basedir,把MY_BASEDIR_VERSION變數值賦值給 basedir

第二部分 通過 執行mysqld_safe命令的當前路徑(pwd)來判斷 basedir,把pwd賦值給 basedir

第三部分 如果前面的判斷都不符合,則最後設定 MY_BASEDIR_VERSION=/usr/local/mysql (上面例子中執行失敗就是因為MY_BASEDIR_VERSION被設定成了 /usr/local/mysql,ledir='/usr/local/mysql/bin')

3. 問題解決

3.1 方案1

    如果二進位制安裝,並且安裝路徑不是/usr/local/mysql(即basedir 不為 /usr/local/mysql),按要求在 basedir 下執行mysqld_safe 命令

3.2 方案2

     在執行 mysqld_safe 命令前,先手動設定 MY_BASEDIR_VERSION 變數為當前 basedir

export MY_BASEDIR_VERSION=/opt/mysql

##這樣在 “First, try to find BASEDIR and ledir (where mysqld is)” 時可以使用該變數,就能對 basedir進行正確的賦值

##注意 mysqld_safe “# Second, try to find the data directory”這部分程式碼中也會用到 MY_BASEDIR_VERSION變數

3.3 方案3

    改寫 mysqld_safe 指令碼,具體怎麼改寫在這裡就不具體說了,如果有需要的朋友可以私下交流