Bug #7249 mysqld_safe silently starts /usr/local/mysql/bin/mysqld rather than bin/mysqld
Submitted: 14 Dec 2004 5:35 Modified: 20 Jul 2005 17:01
Reporter: Tom Dunstan
Status: Closed
Category:Server Severity:S3 (Non-critical)
Version:4.0.22 OS:Sun Solaris (Solaris 9)
Assigned to: Jim Winstead Target Version:

[14 Dec 2004 5: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 21: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 22: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.
[16 Dec 2004 0: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 9:38] Sergei Golubchik
see also bug 7518
[5 Jan 2005 1: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 1:58] Paul DuBois
Mentioned in 4.1.9 change notes.
[20 Feb 2005 23: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 15:56] Sergei Golubchik
Glenn, this looks like a different bug, can you report it separately, please ?
[22 Mar 2005 1: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 17: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 22:26] Michael Stassen
As the problem prevents mysqld from starting, the severity should be changed to S2.
[25 Jun 2005 2: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 12:20] Magnus Blaudd
Approved
[20 Jul 2005 2:56] Jim Winstead
Fixed in 4.1.14 and 5.0.10.
[20 Jul 2005 17:01] Mike Hillyer
Documented in 4-1-14 and 5-0-10 changelogs.