[MDEV-31222] Outdated mysqld_safe script Created: 2023-05-09  Updated: 2023-05-09

Status: Open
Project: MariaDB Server
Component/s: Scripts & Clients
Affects Version/s: 10.11.2
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Anthony Shi Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: mysqld_safe


 Description   

I was looking through the contents of the script and came across a few lines that didn't make sense to me. More specifically from lines 502 to 536 of the script

mysqld_safe(MariaDB)

#
# First, try to find BASEDIR and ledir (where mysqld is)
#
 
MY_PWD=`dirname $0`
MY_PWD=`cd "$MY_PWD"/.. && pwd`
# Check for the directories we would expect from a binary release install
if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION"
then
  # BASEDIR is already overridden on command line.  Do not re-set.
 
  # Use BASEDIR to discover le.
  if test -x "$MY_BASEDIR_VERSION/libexec/mariadbd"
  then
    ledir="$MY_BASEDIR_VERSION/libexec"
  elif test -x "$MY_BASEDIR_VERSION/sbin/mariadbd"
  then
    ledir="$MY_BASEDIR_VERSION/sbin"
  else
    ledir="$MY_BASEDIR_VERSION/bin"
  fi
elif test -x "$MY_PWD/bin/mariadbd"
then
  MY_BASEDIR_VERSION="$MY_PWD"		# Where bin, share and data are
  ledir="$MY_PWD/bin"			# Where mysqld is
# Check for the directories we would expect from a source install
elif test -x "$MY_PWD/libexec/mariadbd"
then
  MY_BASEDIR_VERSION="$MY_PWD"		# Where libexec, share and var are
  ledir="$MY_PWD/libexec"		# Where mysqld is
elif test -x "$MY_PWD/sbin/mariadbd"
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'
  ledir='/usr/bin'
fi

I was wondering what's the purpose of the first condition in the conditional above. What is the purpose of testing for MY_BASEDIR_VERSION when the variable obviously hasn't been set at that point? The comment #BASEDIR already overridden in the command line also didn't make sense to me. How could MY_BASEDIR_VERSION be overridden by the --basedir provided by the user at that point when the command line arguments haven't even been parsed yet? MY_BASEDIR_VERSION can only be overridden when the parse_arguments() function is called, which didn't happen until line 583.

Out of curiosity, I downloaded a copy of MySQL server just to look at MySQL's version of mysqld_safe. Here is what it looks like.

mysqld_safe(MySQL)

find_basedir_from_cmdline () {
  for arg in "$@"; do
    case $arg in
      --basedir=*)
        MY_BASEDIR_VERSION="`echo "$arg" | sed -e 's;^--[^=]*=;;'`"
        # Convert to full path
        cd "$MY_BASEDIR_VERSION"
        if [ $? -ne 0 ] ; then
          log_error "--basedir set to '$MY_BASEDIR_VERSION', however could not access directory"
          exit 1
        fi
        MY_BASEDIR_VERSION="`pwd`"
        ;;
    esac
  done
}
 
#
# First, try to find BASEDIR and ledir (where mysqld is)
#
 
oldpwd="`pwd`"
 
# Args not parsed yet, check if --basedir was given on command line
find_basedir_from_cmdline "$@"
echo "Basedir=$MY_BASEDIR_VERSION"
 
# --basedir is already overridden on command line
if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION" ; then
  # Search for mysqld and set ledir
  for dir in bin libexec sbin bin ; do
    if test -x "$MY_BASEDIR_VERSION/$dir/mysqld" ; then
      ledir="$MY_BASEDIR_VERSION/$dir"
      break
    fi
  done
 
else
  # Basedir should be parent dir of bindir, unless some non-standard
  # layout is used
 
  cd "`dirname $0`"
  if [ -h "$0" ] ; then
    realpath="`ls -l  "$0" | awk '{print $NF}'`"
    cd "`dirname "$realpath"`"
  fi
  cd ..
  MY_PWD="`pwd`"
 
  # Search for mysqld and set ledir and BASEDIR
  for dir in bin libexec sbin bin ; do
    if test -x "$MY_PWD/$dir/mysqld" ; then
      MY_BASEDIR_VERSION="$MY_PWD"
      ledir="$MY_BASEDIR_VERSION/$dir"
      break
    fi
  done
 
  # If we still didn't find anything, use the compiled-in defaults
  if test -z "$MY_BASEDIR_VERSION" ; then
    MY_BASEDIR_VERSION='/usr/local/mysql'
    ledir='/usr/local/mysql/bin'
  fi
fi

The mysqld_safe script distributed with MySQL makes sense to me because it locates the --basedir option from the command line first (via the find_basedir_from_cmdline() function) before attempting to test whether it has been overridden. This led me to wonder if the script shipped with MariaDB is outdated.

UPDATE:

After further investigation, I discovered another aspect of the script that doesn't agree with MariaDB's official documentation. It is implied in the mysqld_safe article on the knowledge base that the script will fallback to using @libexecdir@/mysql/bin as ledir if the directory containing the mysqld_safe script isn't a valid base directory. Now unless I'm mistaken, @libexecdir@ refers to a subdirectory inside /usr/local according to GNU standards.

Again, this logic is implemented in the mysqld_safe script shipped with MySQL 8.0.33, but not in the one shipped with MariaDB 10.11.2-2

mysqld_safe (MariaDB 10.11.2-2)

MY_PWD=`dirname $0`
MY_PWD=`cd "$MY_PWD"/.. && pwd`
# Check for the directories we would expect from a binary release install
if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION"
then
  # BASEDIR is already overridden on command line.  Do not re-set.
.
.
(snipped)
.
.
  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'
  ledir='/usr/bin'
fi

As you can see, in MariaDB's version, mysqld_safe falls back to /usr/bin as the ledir whereas MySQL falls back to /usr/local/mysql/bin as implied in MariaDB's documentation.

mysqld_safe (MySQL 8.0.33)

#
# First, try to find BASEDIR and ledir (where mysqld is)
#
 
oldpwd="`pwd`"
 
# Args not parsed yet, check if --basedir was given on command line
find_basedir_from_cmdline "$@"
 
# --basedir is already overridden on command line
if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION" ; then
.
.
(snipped)
.
.
  # If we still didn't find anything, use the compiled-in defaults
  if test -z "$MY_BASEDIR_VERSION" ; then
    MY_BASEDIR_VERSION='/usr/local/mysql'
    ledir='/usr/local/mysql/bin'
  fi
fi

This once against indicates that MariaDB is using an outdated version of the mysqld_safe script.



 Comments   
Comment by Daniel Black [ 2023-05-09 ]

If you run mysqld_safe --basedir=/somewhere, then the mariadbd exe is looked for under this directory.

Comment by Anthony Shi [ 2023-05-09 ]

Hello, @danblack . Thanks for replying.

If you run mysqld_safe --basedir=/somewhere, then the mariadbd exe is looked for under this directory.

Yes, I'm aware that this was the intent behind this:

MY_PWD=`dirname $0`
MY_PWD=`cd "$MY_PWD"/.. && pwd`
# Check for the directories we would expect from a binary release install
if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION"
then
  # BASEDIR is already overridden on command line.  Do not re-set.
 
  # Use BASEDIR to discover le.
  if test -x "$MY_BASEDIR_VERSION/libexec/mariadbd"
  then
    ledir="$MY_BASEDIR_VERSION/libexec"
  elif test -x "$MY_BASEDIR_VERSION/sbin/mariadbd"
  then
    ledir="$MY_BASEDIR_VERSION/sbin"
  else
    ledir="$MY_BASEDIR_VERSION/bin"
  fi
elif test -x "$MY_PWD/bin/mariadbd"
then
  MY_BASEDIR_VERSION="$MY_PWD"		# Where bin, share and data are
  ledir="$MY_PWD/bin"			# Where mysqld is
# Check for the directories we would expect from a source install
elif test -x "$MY_PWD/libexec/mariadbd"
then
  MY_BASEDIR_VERSION="$MY_PWD"		# Where libexec, share and var are
  ledir="$MY_PWD/libexec"		# Where mysqld is
elif test -x "$MY_PWD/sbin/mariadbd"
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'
  ledir='/usr/bin'
fi

But from what I understand from the script, the condition if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION" will never be true because MY_BASEDIR_VERSION hasn't been set at that point yet because parse_arguments() is called AFTER the condition has already been executed.

The script shipped with MySQL made sense because it calls find_basedir_from_cmdline() first before executing the tests.

Comment by Elena Stepanova [ 2023-05-09 ]

anthony-S93,

Technically, it can be overridden on the command line. Not as an option (which is indeed not parsed yet), but as an environment variable.

MY_BASEDIR_VERSION=/data/bld/10.11 bin/mysqld_safe ....

I would however agree that it probably wasn't the intent.

Comment by Anthony Shi [ 2023-05-09 ]

Hi @elenst. Thank you for your response.

...but as an environment variable.

That's what I thought as well. The user must set MY_BASEDIR_VERSION manually in the shell.

Generated at Thu Feb 08 10:22:11 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.