0

I'm trying to develop a tool to check MariaDB option files to identify potential errors. When I was going through the mysqld_safe shell script in order to understand how it works, I came across these lines (lines 505 to 536, to be exact):

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

What confuses me first and foremost is the comment # BASEDIR is already overriden on command line. Do not re-set. How exactly is $MY_BASEDIR_VERSION set before that line to begin with? The only way (as far as I can tell) for $MY_BASEDIR_VERSION to be set to a user-provided value (either via command line options or an option file) is via the parse_arguments() function defined in lines 293 to 384.

parse_arguments() {
  for arg do
    val=`echo "$arg" | sed -e "s;--[^=]*=;;"`
    case "$arg" in
      # these get passed explicitly to mysqld
      --basedir=*) MY_BASEDIR_VERSION="$val" ;;
      --datadir=*|--data=*) DATADIR="$val" ;;
      --pid[-_]file=*) pid_file="$val" ;;
      --plugin[-_]dir=*) PLUGIN_DIR="$val" ;;
      --user=*) user="$val"; SET_USER=1 ;;
      --group=*) group="$val"; SET_USER=1 ;;
      --log[-_]basename=*|--hostname=*|--loose[-_]log[-_]basename=*)
        pid_file="$val.pid";
    err_log_base="$val";
    ;;
  # these might have been set in a [mysqld_safe] section of my.cnf
  # they are added to mysqld command line to override settings from my.cnf
  --skip[-_]log[-_]error)
    err_log=;
    skip_err_log=1;
    ;;
  --log[-_]error=*)
    err_log="$val";
    skip_err_log=0;
    ;;
  --port=*) mysql_tcp_port="$val" ;;
  --socket=*) mysql_unix_port="$val" ;;

  # mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])!
  --core[-_]file[-_]size=*) core_file_size="$val" ;;
  --ledir=*) ledir="$val" ;;
  --malloc[-_]lib=*) set_malloc_lib "$val" ;;
  --crash[-_]script=*) crash_script="$val" ;;
  --mysqld=*) MYSQLD="$val" ;;
  --mysqld[-_]version=*)
    if test -n "$val"
    then
      MYSQLD="mysqld-$val"
      PLUGIN_VARIANT="/$val"
    else
      MYSQLD="mysqld"
    fi
    ;;
  --dry[-_]run) dry_run=1 ;;
  --nice=*) niceness="$val" ;;
  --nowatch|--no[-_]watch|--no[-_]auto[-_]restart) nowatch=1 ;;
  --open[-_]files[-_]limit=*) open_files="$val" ;;
  --skip[-_]kill[-_]mysqld*) KILL_MYSQLD=0 ;;
  --syslog) want_syslog=1 ;;
  --skip[-_]syslog) want_syslog=0 ;;
  --syslog[-_]tag=*) syslog_tag="$val" ;;
  --timezone=*) TZ="$val"; export TZ; ;;
  --flush[-_]caches) flush_caches=1 ;;
  --numa[-_]interleave) numa_interleave=1 ;;
  --wsrep[-_]on)
    wsrep_on=1
    append_arg_to_args "$arg"
    ;;
  --skip[-_]wsrep[-_]on)
    wsrep_on=0
    append_arg_to_args "$arg"
    ;;
  --wsrep[-_]on=*)
    if echo $val | grep -iq '\(ON\|1\)'; then
      wsrep_on=1
    else
      wsrep_on=0
    fi
    append_arg_to_args "$arg"
    ;;
  --wsrep[-_]urls=*) wsrep_urls="$val"; ;;
  --wsrep[-_]provider=*)
    if test -n "$val" && test "$val" != "none"
    then
      wsrep_restart=1
    fi
    append_arg_to_args "$arg"
    ;;

  --defaults-group-suffix=*) defaults_group_suffix="$arg" ;;

  --help) usage ;;

  *)
    case "$unrecognized_handling" in
      collect) append_arg_to_args "$arg" ;;
      complain) log_error "unknown option '$arg'" ;;
    esac
esac

done }

The problem is that parse_arguments() is first called on line 583 (after the aforementioned conditional tests). So how is it possible for $MY_BASEDIR_VERSION to get overriden on the command line before that?

To me, there are only three conceivable ways for this to occur:

  1. mysqld_safe is re-run somehow after it was first launched (this is possible, but what would be the point in doing so?)
  2. The user set the MY_BASEDIR_VERSION environment variable manually before launching the script.
  3. The MY_BASEDIR_VERSION environment variable is set during MariaDB's installation process.

Having said that, these three possibilities lead to more questions than answers. I have gone through mysqld_safe's documentation but came up empty. I hope somebody here can provide me with the clarification that I need.

Any insight is much appreciated.

Anthony
  • 109
  • 2

1 Answers1

0

There's a number of checks that can only be tested at runtime as it maps to the nature of the pre-installed instance.

What I would do as a check, is:

  1. Install using previous configuration
    D=$(mktemp -d)
    mariadb-install-db --datadir=$D
  1. change configuration to next configuration
    mariadbd --datadir=$D --socket=/tmp/x.sock
    for a in $(seq 10); do [ -S /tmp/x.sock ] && { echo  works; break; }; echo notyet; sleep 1; done
    rm -rf "$D"
  1. if it exits early, there is a configuration error.

Both mariadbd and mariadbd-install-db accept --defaults-file=name as their first argument.

There's possibly still a few edge cases where some variable might depend on datadir, or the nature of hardware/os/filesystem. This should cover the common configuration typos or values out of range.

danblack
  • 8,258
  • 2
  • 12
  • 28