Bug #7249 mysqld_safe silently starts /usr/local/mysql/bin/mysqld rather than bin/mysqld
Submitted: 14 Dec 2004 4:35 Modified: 20 Jul 2005 15:01
Reporter: Tom Dunstan Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:4.0.22 OS:Solaris (Solaris 9)
Assigned to: Jim Winstead CPU Architecture:Any

[14 Dec 2004 4:35] Tom Dunstan
Description:
I had an old mysql installation (4.0.12) sitting in /usr/local/mysql. I installed the 4.0.22 Solaris 9 32 bit binary distribution elsewhere. I wished the new instance to be used by a couple of different mysql processes, using separate data directories. To ensure that I wasn't using the default data directory instead of the new one, I renamed the data directory in the distribution to data-orig. Then I fired up "bin/mysqld_safe --defaults-file=/some/config/file.cnf". I restored the database and everything appeared to be working fine, until the next day when I discovered that the queries which hadn't been working (and hence were the reason for the upgrade) *still* weren't working. Upon connecting to the server, I was astonished to see that the server process was still 4.0.12. After much wasting of time attempting work work out what the heck was going on, I discovered that the mysqld_safe script looks for the existence of the "data" directory under `pwd`, ie ./data, otherwise it assumes that it's not the relative path based binary distribution and ends up silently hardcoding the paths to /usr/local/mysql.

How to repeat:
 - Install binary distro
 - Rename / remove data directory
 - Start up with a config file pointing to a different data directory.

If you have a mysql install in /usr/local/mysql, it will silently use that. Otherwise I would expect it to barf complaining about /usr/local/mysql/bin/mysqld not being found, but I haven't tested it.

Suggested fix:
The check for the data directory should be removed. The only file that the mysqld_safe script should need to exist should be ./bin/mysqld or ./bin/mysqld-max, so the check should be for those instead.
[15 Dec 2004 20:37] Alexander Keremidarski
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.mysql.com/documentation/ and the instructions on
how to report a bug at http://bugs.mysql.com/how-to-report.php
[15 Dec 2004 21:50] Sergei Golubchik
I don't think it's good to make the check more relaxed. After all one can rename everything - e.g. mysqld can be renamed to mysqld-4.0.22 - makes sense, doesn't it ?

The only safe solution if you moved basedir is to use --basedir option, and not to rely on built-in magic that tries to auto-determine you new basedir.
[15 Dec 2004 23:46] Tom Dunstan
*sigh*

The standard usage as described in the INSTALL-BINARY file recommend running bin/mysqld_safe from the extracted directory. If the data directory is specified, I see no reason for the check for the existence of the "data" directory, but that's not the main complaint. What should not happen, in a binary distribution at least, is that a guess should be made about where the stuff is really and *silently* do that. If you're guessing that it's in /usr/local/mysql, then *say* so in the output before firing the mysqld binary up. If not specifying the basedir as a command line option isn't supported, then stop the script and say so. My complaint is that I was doing what I thought was correct according to the documentation that I read, I ran it from the base directory, but it silently ran a different one. I presume that the /usr/local/mysql hardcoding in the script is based on what the --prefix configure option was when built, but that's completely meaningless for a binary distribution.

Regarding the comment about being able to rename anything: I know what you're saying, but that's not the point. I moved the datadir elsewhere, and I specified the datadir as an option to mysqld_safe. Given that moving the datadir appears to be supported given the existence of the command line option, renaming/moving it would not appear to be in the same league as renaming the binary which would obviously break the script. Thus there was no apparent reason to fear that the script would *silently start a completely different version of mysqld*.

I know this has already been classified as not-a-bug, but here are some fairly trivial to implement suggestions:

A way to preserve the existing magical (ie silently revert to the configured prefix rather than the current directory) behaviour of the script but not break it for this case would be to check for the existence of the datadir command line option, and use that in the check for the data dir rather than the hardcoded "data" directory.

If that doesn't meet your approval, then remove the fallback to the configured prefix in the version of the script that gets shipped with the binary, since if it works it would only be by very good luck, whereas it's quite possible that it'll pick up an older version that someone has installed.

If you don't like that, then at the very least print out a warning message when  falling back to /usr/local/mysql, for the same reasons as in the previous paragraph.

Actually, I think that one of the second two should be implemented in the binary release, regardless of whether the first is or not. Implementing the first would just be a nicety.

Thanks

Tom
[24 Dec 2004 8:38] Sergei Golubchik
see also bug 7518
[5 Jan 2005 0:16] Jim Winstead
mysqld_safe no longer tests for the presence of the data directories when using a relatively-
located binary. It just assumes it is there, and will fail to start up if it is not. This allows the 
datadir to be specified on the command line, and avoids running a binary that was not intended. 
(At least as much as the behavior of looking relative to the current working directory makes 
possible.)
[25 Jan 2005 0:58] Paul DuBois
Mentioned in 4.1.9 change notes.
[20 Feb 2005 22:58] Glenn Fleishman
I know this is closed, but I cannot reconcile the information here and in the release notes for 4.1.9 with the fact that if I have datadir defined with an extra default file, it no longer reads that datadir declaration.

That is, I invoke mysqld as follows:

mysqld_safe --defaults-extra-file=/etc/my.main.cf

The /etc/my.cnf file has generic settings and /etc/my.main.cnf contains an entry starting [mysqld] that has the port and datadir settings. This worked until 4.1.9. The port is read correctly, so I know that the datadir setting was disabled. The datadir definition is absolute not relative.

So now I have to invoke it as

mysqld_safe --defaults-extra-file=/etc/my.main.cf --datadir=/path/to/datadir/

Is this a bug or a feature? It feels like something is broken as this behavior wasn't deprecated along with the change associated with this bug report and resolution.
[21 Feb 2005 14:56] Sergei Golubchik
Glenn, this looks like a different bug, can you report it separately, please ?
[22 Mar 2005 0:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[4 Apr 2005 15:25] Michael Stassen
No, no, no.  In fixing one problem, you've created another.  Now mysqld won't start if you build from source using --localstatedir.

Description:
I've always compiled from source with, among other options, 

            --localstatedir=/usr/local/mysql/data

With this change to mysqld_safe, I now get 

/usr/local/mysql: sudo bin/mysqld_safe  
  touch: /usr/local/mysql/var/Whitestar.local.err: No such file or directory
  chown: /usr/local/mysql/var/Whitestar.local.err: No such file or directory
  Starting mysqld daemon with databases from /usr/local/mysql/var
  bin/mysqld_safe: line 302: /usr/local/mysql/var/Whitestar.local.err: No such file or directory
  bin/mysqld_safe: line 308: /usr/local/mysql/var/Whitestar.local.err: No such file or directory
  STOPPING server from pid file /usr/local/mysql/var/Whitestar.local.pid
  tee: /usr/local/mysql/var/Whitestar.local.err: No such file or directory
  050329 17:57:10  mysqld ended
  tee: /usr/local/mysql/var/Whitestar.local.err: No such file or directory

As you can see, mysqld_safe now ignores the compiled-in default, instead assuming that my DATADIR is in var, rather than data.

Analysis:
This happens because mysqld_safe now decides that the data is in var, simply because mysqld is in libexec.  If we allow moving the data directory, then datadir and ledir are independent.  Just as we cannot determine the location of the executable based on the location of the data, as Tom points out, so we also cannot determine the location of the data based on the location of the executable.  

In examining the code for mysqld_safe, I've reached the conclusion that it really doesn't support moving datadir.  There are several spots where this possibility has not been considered, and the current scheme of parsing the command line args last makes it impossible to treat a moved datadir equivalently to a datadir in the expected location.  This is further complicated by the current bug in my_print_defaults (<a href="http://bugs.mysql.com/bug.php?id=9136">bug #9136</a>).

Solutions:
As I see it, there are three options.
1) The easy way out:  Give up on support for moving datadir.  Revert to the previous behavior of mysqld_safe, with prominent warnings that moving the data directory is not supported.

2) The middle road:  Change mysqld_safe to set datadir separately from ledir, but leave the rest as is.  I've included a patch below to do just that.

3) The complete fix.  Start with the patch below, then fix the rest of the issues surrounding moving datadir.  I have some ideas in mind, should you choose this route.

*** mysql-4.1.10/scripts/mysqld_safe.sh Mon Apr  4 14:49:14 2005
--- mysql-4.1.10b/scripts/mysqld_safe.sh        Mon Apr  4 14:40:38 2005
***************
*** 85,112 ****
  
  
  MY_PWD=`pwd`
! # Check if we are starting this relative (for the binary release)
! if test -f ./share/mysql/english/errmsg.sys -a \
!  -x ./bin/mysqld
  then
!   MY_BASEDIR_VERSION=$MY_PWD          # Where bin, share and data are
    ledir=$MY_BASEDIR_VERSION/bin               # Where mysqld is
    DATADIR=$MY_BASEDIR_VERSION/data
    if test -z "$defaults"
    then
!     defaults="--defaults-extra-file=$MY_BASEDIR_VERSION/data/my.cnf"
    fi
! # Check if this is a 'moved install directory'
! elif test -f ./share/mysql/english/errmsg.sys -a \
!  -x ./libexec/mysqld
  then
-   MY_BASEDIR_VERSION=$MY_PWD          # Where libexec, share and var are
-   ledir=$MY_BASEDIR_VERSION/libexec   # Where mysqld is
    DATADIR=$MY_BASEDIR_VERSION/var
  else
-   MY_BASEDIR_VERSION=@prefix@
    DATADIR=@localstatedir@
-   ledir=@libexecdir@
  fi
  
  user=@MYSQLD_USER@
--- 85,120 ----
  
  
  MY_PWD=`pwd`
! # Find mysqld, in case we moved the installation diirectory and are
! # starting this relative, then set MY_BASEDIR_VERSION and ledir accordingly.
! #  Binary release?  Check in ./bin
! if test -f ./share/mysql/english/errmsg.sys -a -x ./bin/mysqld
  then
!   MY_BASEDIR_VERSION=$MY_PWD          # Where bin and share are
    ledir=$MY_BASEDIR_VERSION/bin               # Where mysqld is
+ #  Source build?  Check in ./libexec
+ elif test -f ./share/mysql/english/errmsg.sys -a -x ./libexec/mysqld
+ then
+   MY_BASEDIR_VERSION=$MY_PWD          # Where libexec and share are
+   ledir=$MY_BASEDIR_VERSION/libexec   # Where mysqld is
+ else
+   # We didn't find mysqld in current directory, so use compiled-in defaults
+   MY_BASEDIR_VERSION=@prefix@
+   ledir=@libexecdir@
+ fi
+ 
+ if test -d $MY_PWD/data/mysql
+ then
    DATADIR=$MY_BASEDIR_VERSION/data
    if test -z "$defaults"
    then
!     defaults="--defaults-extra-file=$DATADIR/my.cnf"
    fi
! elif test -f ./var/mysql/db.frm
  then
    DATADIR=$MY_BASEDIR_VERSION/var
  else
    DATADIR=@localstatedir@
  fi
  
  user=@MYSQLD_USER@
[3 May 2005 20:26] Michael Stassen
As the problem prevents mysqld from starting, the severity should be changed to S2.
[25 Jun 2005 0:13] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/26422
[29 Jun 2005 10:20] Magnus BlÄudd
Approved
[20 Jul 2005 0:56] Jim Winstead
Fixed in 4.1.14 and 5.0.10.
[20 Jul 2005 15:01] Mike Hillyer
Documented in 4-1-14 and 5-0-10 changelogs.