Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-6565

search order for my.cnf inconsistent in docs/use, and global override with build-time -DDEFAULT_SYSCONFDIR is ignored

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 10.0.13
    • Fix Version/s: 10.0.14
    • Component/s: None
    • Labels:
      None
    • Environment:
      src build of MariaDB v10.0.13 (r4346)

      mysqld -V
      mysqld Ver 10.0.13-MariaDB for Linux on x86_64 (Source distribution)

      Description

      I've built/installed MariaDB v10.0.13 (r4346) from src.

      	mysqld -V
      		mysqld  Ver 10.0.13-MariaDB for Linux on x86_64 (Source distribution)
       

      My build config includes

      	cmake ..  --debug-output \
      		-DCMAKE_BUILD_TYPE="Release" \
      		-DCMAKE_INSTALL_PREFIX=/usr/local/mariadb \
      		-DINSTALL_LAYOUT=STANDALONE \
      		-DINSTALL_SYSCONFDIR=/usr/local/etc/mariadb.DEFAULT \
      		-DINSTALL_SYSCONF2DIR=/usr/local/etc/mariadb.DEFAULT/conf.d \
      		-DDEFAULT_SYSCONFDIR=/usr/local/etc/mariadb \
      		...
       

      With this config, and the 'docs' below, a config in

      	/usr/local/etc/mariadb/my.cnf
       

      should be searched for, found, and used.

      It's not.

      Here's the ENV.

      MariaDB (via systemd) is launched with

      	/usr/local/mariadb/bin/mysqld --defaults-file=/usr/local/etc/mariadb/my.cnf --basedir=/usr/local/mariadb --datadir=/var/db/mariadb --plugin-dir=/usr/local/mariadb/lib/plugin --log-error=/var/log/mariadb/mariadb-err.log --pid-file=/var/cache/mariadb/mariadb.pid --socket=/var/cache/mariadb/mariadb.sock --port=3306
       

      Note

      	cat CMakeLists.txt
      		...
      		IF(INSTALL_SYSCONFDIR)
      		  SET(DEFAULT_SYSCONFDIR "${INSTALL_SYSCONFDIR}")
      		ENDIF()
      		...
       
      &
       
      	cat ./cmake/install_layout.cmake
      		...
      		# - INSTALL_SYSCONFDIR      (my.cnf config file. Usually /etc or nothing)
      		# - INSTALL_SYSCONF2DIR     (additional config files, e.g. /etc/mysql/conf.d)
      		...
       
      &
       
      cat ./scripts/CMakeLists.txt
      	...
      	IF(INSTALL_SYSCONFDIR)
      	  SET(sysconfdir ${DEFAULT_SYSCONFDIR})
      	ELSE()
      	  SET(sysconfdir "/etc")
      	ENDIF()
      	...
       
      & 
      	cat ./mysys/my_default.c
      		...
      		/* Which directories are searched for options (and in which order) */
      		...
      		/*
      		   This structure defines the context that we pass to callback
      		   function 'handle_default_option' used in search_default_file
      		   to process each option. This context is used if search_default_file
      		   was called from load_defaults.
      		*/
      		  
      		struct handle_option_ctx
      		...
      		/**
      		  Create the list of default directories.
       
      		  @param alloc  MEM_ROOT where the list of directories is stored
       
      		  @details
      		  The directories searched, in order, are:
      		  - Windows:     GetSystemWindowsDirectory()
      		  - Windows:     GetWindowsDirectory()
      		  - Windows:     C:/
      		  - Windows:     Directory above where the executable is located
      		  - Unix:        /etc/ or the value of DEFAULT_SYSCONFDIR, if defined
      		  - Unix:        /etc/mysql/ unless DEFAULT_SYSCONFDIR is defined
      		  - ALL:         getenv("MYSQL_HOME")
      		  - ALL:         --defaults-extra-file=<path> (run-time option)
      		  - Unix:        ~/
       
      		  On all systems, if a directory is already in the list, it will be moved
      		  to the end of the list.  This avoids reading defaults files multiple times,
      		  while ensuring the correct precedence.
       
      		  @retval NULL  Failure (out of memory, probably)
      		  @retval other Pointer to NULL-terminated array of default directories
      		*/
      		...
       
      &
       
      	@ https://mariadb.com/kb/en/mariadb/documentation/getting-started/configuring-mariadb-with-mycnf/
       
      		On a Linux, Unix or Mac server, MariaDB looks for the my.cnf file in the following locations:
       
      		Location            Scope
      		/etc/my.cnf         Global
      		/etc/mysql/my.cnf   Global
      		SYSCONFDIR/my.cnf   Global
      		$MYSQL_HOME/my.cnf  Server
      		defaults-extra-file File specified with --defaults-extra-file=path, if any
      		/.my.cnf            User
       
      		    SYSCONFDIR is the directory specified with the CMake SYSCONFDIR option when MariaDB was built, by default etc under the compiled-in installation directory. 
       

      With x.13, changes to my config in

      	/usr/local/etc/mariadb/my.cnf
       

      are NOT correctly picked up by any mysql client tools.

      For example, if in my.cnf I add

      	...
      	[client]
      	user = root
      	password = 'XXXXXX'
      	...
       

      and it's correctly picked up, then at shell, instead of

      	mysqlshow -u root -p
      		password: XXXXXX
       

      I should be able to just

      	mysqlshow
       

      with the in-config, specified user= & password= optiont picked up.

      But, with MariaDB 10.0.13, config file changes are simply ignored.

      Checking, If I

      	strace mysqlshow
       

      I see

      	...
      	stat("/usr/local/etc/mariadb.DEFAULT/my.cnf", {st_mode=S_IFREG|0644, st_size=202, ...}) = 0
      	open("/usr/local/etc/mariadb.DEFAULT/my.cnf", O_RDONLY) = 3
      	fstat(3, {st_mode=S_IFREG|0644, st_size=202, ...}) = 0
      	mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1db94ec000
      	read(3, "#\n# This group is read both both"..., 4096) = 202
      	openat(AT_FDCWD, "/etc/my.cnf.d/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
      	getdents(4, /* 3 entries */, 32768)     = 88
      	getdents(4, /* 0 entries */, 32768)     = 0
      	close(4)                                = 0
      	stat("/etc/my.cnf.d/default_plugins.cnf", {st_mode=S_IFREG|0640, st_size=122, ...}) = 0
      	open("/etc/my.cnf.d/default_plugins.cnf", O_RDONLY) = 4
      	fstat(4, {st_mode=S_IFREG|0640, st_size=122, ...}) = 0
      	mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1db94eb000
      	read(4, "[server]\n#plugin-load=blackhole="..., 4096) = 122
      	read(4, "", 4096)                       = 0
      	close(4)                                = 0
      	munmap(0x7f1db94eb000, 4096)            = 0
      	read(3, "", 4096)                       = 0
      	close(3)                                = 0
      	munmap(0x7f1db94ec000, 4096)            = 0
      	stat("/root/.my.cnf", {st_mode=S_IFREG|0644, st_size=8792, ...}) = 0
      	open("/root/.my.cnf", O_RDONLY)         = 3
      	...
       

      Notice,

      	stat("/usr/local/etc/mariadb.DEFAULT/my.cnf", {st_mode=S_IFREG|0644, st_size=202, ...}) = 0
      	open("/usr/local/etc/mariadb.DEFAULT/my.cnf", O_RDONLY) = 3
       

      then

      	stat("/root/.my.cnf", {st_mode=S_IFREG|0644, st_size=8792, ...}) = 0
      	open("/root/.my.cnf", O_RDONLY)         = 3
       

      is searched. There's no indication at all that the specified dir

      	-DDEFAULT_SYSCONFDIR=/usr/local/etc/mariadb \
       

      is searched.

      This is consistent with

      	$ mysqldump --help
      		...
      		Default options are read from the following files in the given order:
      		/usr/local/etc/mariadb.DEFAULT/my.cnf ~/.my.cnf 
      		...
       

      where, as in the strace ^^^, that those are the ONLY two locations checked – DESPITE having specified all of

      		-DINSTALL_SYSCONFDIR=/usr/local/etc/mariadb.DEFAULT \
      		-DINSTALL_SYSCONF2DIR=/usr/local/etc/mariadb.DEFAULT/conf.d \
      		-DDEFAULT_SYSCONFDIR=/usr/local/etc/mariadb \
       

      Verifying what DOES work, starting with

      	ls -al /usr/local/etc/mariadb/my.cnf /etc/my.cnf /root/.my.cnf
      		ls: cannot access /etc/my.cnf: No such file or directory
      		ls: cannot access /root/.my.cnf: No such file or directory
      		-rw-r--r--+ 1 root mysql 8.7K Aug 11 17:48 /usr/local/etc/mariadb/my.cnf
       

      given a config that includes

      	grep "\[client\]" /usr/local/etc/mariadb/my.cnf -A2
      		[client]
      		user                            = root
      		password                        = 'xxxxxx'
       

      the file's only picked up if it exists in /root/.my.cnf

      	mysqlshow
      		mysqlshow: Access denied for user 'root'@'localhost' (using password: NO)
       
      	ln -sf /usr/local/etc/mariadb/my.cnf /etc/my.cnf
      	mysqlshow
      		mysqlshow: Access denied for user 'root'@'localhost' (using password: NO)
       
      	rm -f /etc/my.cnf
      	ln -sf /usr/local/etc/mariadb/my.cnf /root/.my.cnf
      	mysqlshow
      		+------------------------------+
      		|          Databases           |
      		+------------------------------+
      		| information_schema           |
      		| mysql                        |
      		| performance_schema           |
      		| test                         |
      		+------------------------------+
       

      Bottom line:

      The docs and behavior of default config-file location/use are inconsistent (and likely have been for years).

      There should be a clear, consistent, documented search order, and an option to override – at build- (maybe run-, too) time with an abolute/exclusive location.

      The current 'right' config option should be

      	-DDEFAULT_SYSCONFDIR= /path/to/dir/that/contains/my.cnf/
       

      which, if defined, should limit search path to ONLY that dir, overriding all other search paths.

        Attachments

          Activity

            People

            Assignee:
            serg Sergei Golubchik
            Reporter:
            grantk GrantK
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: