1 # Copyright 1999-2020 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
6 CMAKE_MAKEFILE_GENERATOR=emake
8 inherit cmake-utils flag-o-matic linux-info \
9 multiprocessing prefix toolchain-funcs check-reqs
15 PATCH_SET="https://dev.gentoo.org/~whissi/dist/mysql/${PN}-8.0.20-patches-01.tar.xz"
17 SRC_URI="https://cdn.mysql.com/Downloads/MySQL-8.0/mysql-boost-${MY_PV}.tar.gz
18 https://cdn.mysql.com/archives/mysql-8.0/mysql-boost-${MY_PV}.tar.gz
19 http://downloads.mysql.com/archives/MySQL-8.0/${PN}-boost-${MY_PV}.tar.gz
22 HOMEPAGE="https://www.mysql.com/"
23 DESCRIPTION="A fast, multi-threaded, multi-user SQL database server"
26 IUSE="cjk cracklib debug jemalloc latin1 libressl numa +perl profiling
27 router selinux +server tcmalloc test"
29 # Tests always fail when libressl is enabled due to hard-coded ciphers in the tests
30 RESTRICT="!test? ( test ) libressl? ( test )"
32 REQUIRED_USE="?? ( tcmalloc jemalloc )
40 KEYWORDS="amd64 arm arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc x86 ~amd64-linux ~x86-linux ~x64-macos ~x86-macos ~x64-solaris ~x86-solaris"
42 # Shorten the path because the socket path length must be shorter than 107 chars
43 # and we will run a mysql server during test phase
46 # Be warned, *DEPEND are version-dependant
47 # These are used for both runtime and compiletime
49 >=app-arch/lz4-0_p131:=
51 >=sys-libs/zlib-1.2.3:0=
52 libressl? ( dev-libs/libressl:0= )
53 !libressl? ( >=dev-libs/openssl-1.0.0:0= )
57 >=dev-libs/protobuf-3.8:=
59 cjk? ( app-text/mecab:= )
60 jemalloc? ( dev-libs/jemalloc:0= )
65 numa? ( sys-process/numactl )
66 tcmalloc? ( dev-util/google-perftools:0= )
69 DEPEND="${COMMON_DEPEND}
70 || ( >=sys-devel/gcc-3.4.6 >=sys-devel/gcc-apple-4.0 )
72 server? ( net-libs/rpcsvc-proto )
74 acct-group/mysql acct-user/mysql
78 RDEPEND="${COMMON_DEPEND}
79 !dev-db/mariadb !dev-db/mariadb-galera !dev-db/percona-server !dev-db/mysql-cluster
80 selinux? ( sec-policy/selinux-mysql )
82 acct-group/mysql acct-user/mysql
83 dev-db/mysql-init-scripts
86 # For other stuff to bring us in
87 # dev-perl/DBD-mysql is needed by some scripts installed by MySQL
88 PDEPEND="perl? ( >=dev-perl/DBD-mysql-2.9004 )"
90 CHECKREQS_DISK_BUILD="8G"
93 : ${MY_SHAREDSTATEDIR="${EPREFIX}/usr/share/mysql"}
94 : ${MY_SYSCONFDIR="${EPREFIX}/etc/mysql"}
95 : ${MY_LOCALSTATEDIR="${EPREFIX}/var/lib/mysql"}
96 : ${MY_LOGDIR="${EPREFIX}/var/log/mysql"}
97 MY_DATADIR="${MY_LOCALSTATEDIR}"
99 export MY_SHAREDSTATEDIR MY_SYSCONFDIR
100 export MY_LOCALSTATEDIR MY_LOGDIR
105 [[ ${MERGE_TYPE} == binary ]] && return
106 use server && check-reqs_pkg_pretend
110 [[ ${MERGE_TYPE} == binary ]] && return
112 if has test ${FEATURES} ; then
113 # Bug #213475 - MySQL _will_ object strenuously if your machine is named
114 # localhost. Also causes weird failures.
115 [[ "${HOSTNAME}" == "localhost" ]] && die "Your machine must NOT be named localhost"
117 if ! has userpriv ${FEATURES} ; then
118 die "Testing with FEATURES=-userpriv is no longer supported by upstream. Tests MUST be run as non-root."
121 local aio_max_nr=$(sysctl -n fs.aio-max-nr 2>/dev/null)
122 [[ -z "${aio_max_nr}" || ${aio_max_nr} -lt 250000 ]] \
123 && die "FEATURES=test will require fs.aio-max-nr=250000 at minimum!"
126 # Upstream only supports tests with default charset
127 die "Testing with USE=latin1 is not supported."
131 if use kernel_linux ; then
133 linux-info_get_any_version
135 local CONFIG_CHECK="~NUMA"
137 local WARNING_NUMA="This package expects NUMA support in kernel which this system does not have at the moment;"
138 WARNING_NUMA+=" Either expect runtime errors, enable NUMA support in kernel or rebuild the package without NUMA support"
144 use server && check-reqs_pkg_setup
150 mv -f "${WORKDIR}/${MY_P}" "${S}" || die
154 eapply "${WORKDIR}"/mysql-patches
158 # Avoid rpm call which would trigger sandbox, #692368
160 -e 's/MY_RPM rpm/MY_RPM rpmNOTEXISTENT/' \
161 CMakeLists.txt || die
163 if use jemalloc ; then
164 echo "TARGET_LINK_LIBRARIES(mysqld jemalloc)" >> "${S}/sql/CMakeLists.txt" || die
167 if use tcmalloc ; then
168 echo "TARGET_LINK_LIBRARIES(mysqld tcmalloc)" >> "${S}/sql/CMakeLists.txt" || die
171 # Remove the centos and rhel selinux policies to support mysqld_safe under SELinux
172 if [[ -d "${S}/support-files/SELinux" ]] ; then
173 echo > "${S}/support-files/SELinux/CMakeLists.txt" || die
176 # Remove man pages for client-lib tools we don't install
178 man/my_print_defaults.1 \
180 man/zlib_decompress.1 \
183 cmake-utils_src_prepare
187 # Bug #114895, bug #110149
188 filter-flags "-O" "-O[01]"
190 append-cxxflags -felide-constructors
192 # bug #283926, with GCC4.4, this is required to get correct behavior.
193 append-flags -fno-strict-aliasing
195 CMAKE_BUILD_TYPE="RelWithDebInfo"
197 # debug hack wrt #497532
199 -DCMAKE_C_FLAGS_RELWITHDEBINFO="$(usex debug '' '-DNDEBUG')"
200 -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="$(usex debug '' '-DNDEBUG')"
201 -DMYSQL_DATADIR="${EPREFIX}/var/lib/mysql"
202 -DSYSCONFDIR="${EPREFIX}/etc/mysql"
204 -DINSTALL_DOCDIR=share/doc/${PF}
205 -DINSTALL_DOCREADMEDIR=share/doc/${PF}
206 -DINSTALL_INCLUDEDIR=include/mysql
207 -DINSTALL_INFODIR=share/info
208 -DINSTALL_LIBDIR=$(get_libdir)
209 -DINSTALL_MANDIR=share/man
210 -DINSTALL_MYSQLSHAREDIR=share/mysql
211 -DINSTALL_PLUGINDIR=$(get_libdir)/mysql/plugin
212 -DINSTALL_MYSQLDATADIR="${EPREFIX}/var/lib/mysql"
213 -DINSTALL_SBINDIR=sbin
214 -DINSTALL_SUPPORTFILESDIR="${EPREFIX}/usr/share/mysql"
215 -DCOMPILATION_COMMENT="Gentoo Linux ${PF}"
216 -DWITH_UNIT_TESTS=$(usex test ON OFF)
217 # Using bundled editline to get CTRL+C working
218 -DWITH_EDITLINE=bundled
222 -DENABLED_LOCAL_INFILE=1
223 -DMYSQL_UNIX_ADDR="${EPREFIX}/var/run/mysqld/mysqld.sock"
224 -DWITH_DEFAULT_COMPILER_OPTIONS=0
225 -DWITH_DEFAULT_FEATURE_SET=0
226 # The build forces this to be defined when cross-compiling. We pass it
227 # all the time for simplicity and to make sure it is actually correct.
228 -DSTACK_DIRECTION=$(tc-stack-grows-down && echo -1 || echo 1)
229 -DCMAKE_POSITION_INDEPENDENT_CODE=ON
231 -DWITH_BOOST="${S}/boost"
232 -DWITH_ROUTER=$(usex router ON OFF)
235 if is-flagq -fno-lto ; then
236 einfo "LTO disabled via {C,CXX,F,FC}FLAGS"
237 mycmakeargs+=( -DWITH_LTO=OFF )
238 elif is-flagq -flto ; then
239 einfo "LTO forced via {C,CXX,F,FC}FLAGS"
240 myconf+=( -DWITH_LTO=ON )
243 myconf+=( -DWITH_LTO=OFF )
247 mycmakeargs+=( -DINSTALL_MYSQLTESTDIR=share/mysql/mysql-test )
249 mycmakeargs+=( -DINSTALL_MYSQLTESTDIR='' )
252 mycmakeargs+=( -DWITHOUT_CLIENTLIBS=YES )
257 # Our dev-libs/rapidjson doesn't carry necessary fixes for std::regex
258 -DWITH_RAPIDJSON=bundled
261 if [[ -n "${MYSQL_DEFAULT_CHARSET}" && -n "${MYSQL_DEFAULT_COLLATION}" ]] ; then
262 ewarn "You are using a custom charset of ${MYSQL_DEFAULT_CHARSET}"
263 ewarn "and a collation of ${MYSQL_DEFAULT_COLLATION}."
264 ewarn "You MUST file bugs without these variables set."
265 ewarn "Tests will probably fail!"
268 -DDEFAULT_CHARSET=${MYSQL_DEFAULT_CHARSET}
269 -DDEFAULT_COLLATION=${MYSQL_DEFAULT_COLLATION}
271 elif use latin1 ; then
273 -DDEFAULT_CHARSET=latin1
274 -DDEFAULT_COLLATION=latin1_swedish_ci
278 -DDEFAULT_CHARSET=utf8mb4
279 -DDEFAULT_COLLATION=utf8mb4_0900_ai_ci
285 -DWITH_EXTRA_CHARSETS=all
286 -DWITH_DEBUG=$(usex debug)
287 -DWITH_MECAB=$(usex cjk system OFF)
288 -DWITH_LIBEVENT=system
289 -DWITH_PROTOBUF=system
290 -DWITH_NUMA=$(usex numa ON OFF)
293 if use profiling ; then
294 # Setting to OFF doesn't work: Once set, profiling options will be added
295 # to `mysqld --help` output via sql/sys_vars.cc causing
296 # "main.mysqld--help-notwin" test to fail
297 mycmakeargs+=( -DENABLED_PROFILING=ON )
302 -DWITH_EXAMPLE_STORAGE_ENGINE=0
303 -DWITH_ARCHIVE_STORAGE_ENGINE=1
304 -DWITH_BLACKHOLE_STORAGE_ENGINE=1
305 -DWITH_CSV_STORAGE_ENGINE=1
306 -DWITH_FEDERATED_STORAGE_ENGINE=1
307 -DWITH_HEAP_STORAGE_ENGINE=1
308 -DWITH_INNOBASE_STORAGE_ENGINE=1
309 -DWITH_INNODB_MEMCACHED=0
310 -DWITH_MYISAMMRG_STORAGE_ENGINE=1
311 -DWITH_MYISAM_STORAGE_ENGINE=1
320 cmake-utils_src_configure
323 # Official test instructions:
324 # ulimit -n 16500 && \
325 # USE='perl server' \
326 # FEATURES='test userpriv' \
327 # ebuild mysql-X.X.XX.ebuild \
328 # digest clean package
331 local rawtestname bug reason
332 rawtestname="${1}" ; shift
335 ewarn "test '${rawtestname}' disabled: '${reason}' (BUG#${bug})"
336 echo ${rawtestname} : BUG#${bug} ${reason} >> "${T}/disabled.def"
339 local TESTDIR="${BUILD_DIR}/mysql-test"
341 local retstatus_tests
343 # Run CTest (test-units)
347 # Ensure that parallel runs don't die
348 export MTR_BUILD_THREAD="$((${RANDOM} % 100))"
350 if [[ -z "${MTR_PARALLEL}" ]] ; then
351 local -x MTR_PARALLEL=$(makeopts_jobs)
353 if [[ ${MTR_PARALLEL} -gt 4 ]] ; then
354 # Running multiple tests in parallel usually require higher ulimit
355 # and fs.aio-max-nr setting. In addition, tests like main.multi_update
356 # are known to hit timeout when system is busy.
357 # To avoid test failure we will limit MTR_PARALLEL to 4 instead of
359 local info_msg="Parallel MySQL test suite jobs limited to 4 (MAKEOPTS=${MTR_PARALLEL})"
360 info_msg+=" to avoid test failures. Set MTR_PARALLEL if you know what you are doing!"
366 einfo "MTR_PARALLEL is set to '${MTR_PARALLEL}'"
369 # create directories because mysqladmin might run out of order
370 mkdir -p "${T}"/var-tests{,/log} || die
373 pushd "${TESTDIR}" &>/dev/null || die
375 touch "${T}/disabled.def"
377 local -a disabled_tests
378 disabled_tests+=( "auth_sec.keyring_file_data_qa;0;Won't work with user privileges" )
379 disabled_tests+=( "gis.spatial_analysis_functions_buffer;5452;Known rounding error with latest AMD processors (PS)" )
380 disabled_tests+=( "gis.gis_bugs_crashes;5452;Known rounding error with latest AMD processors (PS)" )
381 disabled_tests+=( "gis.geometry_class_attri_prop;5452;Known rounding error with latest AMD processors (PS)" )
382 disabled_tests+=( "gis.spatial_utility_function_distance_sphere;5452;Known rounding error with latest AMD processors (PS)" )
383 disabled_tests+=( "gis.geometry_property_function_issimple;5452;Known rounding error with latest AMD processors (PS)" )
384 disabled_tests+=( "gis.spatial_analysis_functions_centroid;5452;Known rounding error with latest AMD processors (PS)" )
385 disabled_tests+=( "gis.spatial_operators_intersection;5452;Known rounding error with latest AMD processors (PS)" )
386 disabled_tests+=( "gis.spatial_utility_function_simplify;5452;Known rounding error with latest AMD processors (PS)" )
387 disabled_tests+=( "gis.spatial_op_testingfunc_mix;5452;Known rounding error with latest AMD processors (PS)" )
388 disabled_tests+=( "gis.spatial_analysis_functions_distance;5452;Known rounding error with latest AMD processors (PS)" )
389 disabled_tests+=( "main.window_std_var;0;Known rounding error with latest AMD processors -- no upstream bug yet" )
390 disabled_tests+=( "main.window_std_var_optimized;0;Known rounding error with latest AMD processors -- no upstream bug yet" )
391 disabled_tests+=( "main.with_recursive;0;Known rounding error with latest AMD processors -- no upstream bug yet" )
392 disabled_tests+=( "rpl_gtid.rpl_gtid_stm_drop_table;90612;Known test failure" )
393 disabled_tests+=( "rpl_gtid.rpl_multi_source_mtr_includes;0;Known failure - no upstream bug yet" )
394 disabled_tests+=( "sys_vars.myisam_data_pointer_size_func;87935;Test will fail on slow hardware")
395 disabled_tests+=( "x.connection;0;Known failure - no upstream bug yet" )
396 disabled_tests+=( "main.mysqlpump_basic_lz4;0;Extra tool output causes false positive" )
397 disabled_tests+=( "x.message_compressed_payload;0;False positive caused by protobuff-3.11+" )
398 disabled_tests+=( "x.message_protobuf_nested;0;False positive caused by protobuff-3.11+" )
400 if ! hash zip 1>/dev/null 2>&1 ; then
401 # no need to force dep app-arch/zip for one test
402 disabled_tests+=( "innodb.partition_upgrade_create;0;Requires app-arch/zip" )
405 local test_infos_str test_infos_arr
406 for test_infos_str in "${disabled_tests[@]}" ; do
407 IFS=';' read -r -a test_infos_arr <<< "${test_infos_str}"
409 if [[ ${#test_infos_arr[@]} != 3 ]] ; then
410 die "Invalid test data set, not matching format: ${test_infos_str}"
413 _disable_test "${test_infos_arr[0]}" "${test_infos_arr[1]}" "${test_infos_arr[2]}"
415 unset test_infos_str test_infos_arr
417 # Try to increase file limits to increase test coverage
418 if ! ulimit -n 16500 1>/dev/null 2>&1 ; then
419 # Upper limit comes from parts.partition_* tests
420 ewarn "For maximum test coverage please raise open file limit to 16500 (ulimit -n 16500) before calling the package manager."
422 if ! ulimit -n 4162 1>/dev/null 2>&1 ; then
423 # Medium limit comes from '[Warning] Buffered warning: Could not increase number of max_open_files to more than 3000 (request: 4162)'
424 ewarn "For medium test coverage please raise open file limit to 4162 (ulimit -n 4162) before calling the package manager."
426 if ! ulimit -n 3000 1>/dev/null 2>&1 ; then
427 ewarn "For minimum test coverage please raise open file limit to 3000 (ulimit -n 3000) before calling the package manager."
429 einfo "Will run test suite with open file limit set to 3000 (minimum test coverage)."
432 einfo "Will run test suite with open file limit set to 4162 (medium test coverage)."
435 einfo "Will run test suite with open file limit set to 16500 (best test coverage)."
438 # run mysql-test tests
439 perl mysql-test-run.pl --force --vardir="${T}/var-tests" --reorder --skip-test=tokudb --skip-test-list="${T}/disabled.def"
442 popd &>/dev/null || die
444 # Cleanup is important for these testcases.
445 pkill -9 -f "${S}/ndb" 2>/dev/null
446 pkill -9 -f "${S}/sql" 2>/dev/null
449 [[ $retstatus_unit -eq 0 ]] || failures="${failures} test-unit"
450 [[ $retstatus_tests -eq 0 ]] || failures="${failures} tests"
452 [[ -z "$failures" ]] || die "Test failures: $failures"
453 einfo "Tests successfully completed"
457 cmake-utils_src_install
459 # Make sure the vars are correctly initialized
463 einfo "Making Convenience links for mysqlcheck multi-call binary"
464 dosym "mysqlcheck" "/usr/bin/mysqlanalyze"
465 dosym "mysqlcheck" "/usr/bin/mysqlrepair"
466 dosym "mysqlcheck" "/usr/bin/mysqloptimize"
468 # INSTALL_LAYOUT=STANDALONE causes cmake to create a /usr/data dir
469 if [[ -d "${ED}/usr/data" ]] ; then
470 rm -Rf "${ED}/usr/data" || die
473 # Unless they explicitly specific USE=test, then do not install the
474 # testsuite. It DOES have a use to be installed, esp. when you want to do a
475 # validation of your database configuration after tuning it.
477 rm -rf "${ED}/${MY_SHAREDSTATEDIR#${EPREFIX}}/mysql-test"
480 # Configuration stuff
481 einfo "Building default configuration ..."
482 insinto "${MY_SYSCONFDIR#${EPREFIX}}"
483 [[ -f "${S}/scripts/mysqlaccess.conf" ]] && doins "${S}"/scripts/mysqlaccess.conf
484 cp "${FILESDIR}/my.cnf-5.7" "${TMPDIR}/my.cnf" || die
485 eprefixify "${TMPDIR}/my.cnf"
486 doins "${TMPDIR}/my.cnf"
487 insinto "${MY_SYSCONFDIR#${EPREFIX}}/mysql.d"
488 cp "${FILESDIR}/my.cnf-8.0.distro-client" "${TMPDIR}/50-distro-client.cnf" || die
489 eprefixify "${TMPDIR}/50-distro-client.cnf"
490 doins "${TMPDIR}/50-distro-client.cnf"
492 mycnf_src="my.cnf-8.0.distro-server"
493 sed -e "s!@DATADIR@!${MY_DATADIR}!g" \
494 "${FILESDIR}/${mycnf_src}" \
495 > "${TMPDIR}/my.cnf.ok" || die
498 sed -i -r -e '/^user[[:space:]]*=[[:space:]]*mysql$/d' \
499 "${TMPDIR}/my.cnf.ok" || die
504 -e "/character-set/s|utf8mb4|latin1|g" \
505 "${TMPDIR}/my.cnf.ok" || die
508 eprefixify "${TMPDIR}/my.cnf.ok"
510 newins "${TMPDIR}/my.cnf.ok" 50-distro-server.cnf
512 #Remove mytop if perl is not selected
513 [[ -e "${ED}/usr/bin/mytop" ]] && ! use perl && rm -f "${ED}/usr/bin/mytop"
517 "${ED}/usr/LICENSE.router" \
518 "${ED}/usr/README.router" \
524 # Kill old libmysqclient_r symlinks if they exist. Time to fix what depends on them.
525 find "${D}" -name 'libmysqlclient_r.*' -type l -delete || die
529 # Make sure the vars are correctly initialized
532 # Create log directory securely if it does not exist
533 # NOTE: $MY_LOGDIR contains $EPREFIX by default
534 [[ -d "${MY_LOGDIR}" ]] || install -d -m0750 -o mysql -g mysql "${MY_LOGDIR}"
536 # Note about configuration change
538 elog "This version of ${PN} reorganizes the configuration from a single my.cnf"
539 elog "to several files in /etc/mysql/mysql.d."
540 elog "Please backup any changes you made to /etc/mysql/my.cnf"
541 elog "and add them as a new file under /etc/mysql/mysql.d with a .cnf extension."
542 elog "You may have as many files as needed and they are read alphabetically."
543 elog "Be sure the options have the appropriate section headers, i.e. [mysqld]."
546 if [[ -z "${REPLACING_VERSIONS}" ]] ; then
548 elog "You might want to run:"
549 elog " \"emerge --config =${CATEGORY}/${PF}\""
550 elog "if this is a new install."
554 elog "Upgrade process for ${PN}-8.x has changed. Please read"
555 elog "https://dev.mysql.com/doc/refman/8.0/en/upgrade-binary-package.html"
564 local extra_options="${3}"
566 "${my_print_defaults_binary}"
570 local results=( $(eval "${cmd[@]}" 2>/dev/null | sed -n "/^${flag}/s,${flag},,gp") )
572 if [[ ${#results[@]} -gt 0 ]] ; then
573 # When option is set multiple times only return last value
574 echo "${results[-1]}"
579 # emktemp has no --dry-run option
580 local template="${1}"
582 if [[ -z "${template}" ]] ; then
583 if [[ -z "${T}" ]] ; then
584 template="/tmp/XXXXXXX"
586 template="${T}/XXXXXXX"
590 local template_wo_X=${template//X/}
592 let n_X=${#template}-${#template_wo_X}
593 if [[ ${n_X} -lt 3 ]] ; then
594 echo "${FUNCNAME[0]}: too few X's in template ‘${template}’" >&2
599 local character tmpfile
600 while [[ true ]] ; do
601 let attempts=attempts+1
604 while read -n1 character ; do
605 if [[ "${character}" == "X" ]] ; then
606 tmpfile+="${RANDOM:0:1}"
608 tmpfile+="${character}"
610 done < <(echo -n "${template}")
612 if [[ ! -f "${tmpfile}" ]]
618 if [[ ${attempts} -ge 100 ]] ; then
619 echo "${FUNCNAME[0]}: Cannot create temporary file after 100 attempts." >&2
625 local mysqld_binary="${EROOT}/usr/sbin/mysqld"
626 if [[ ! -x "${mysqld_binary}" ]] ; then
627 die "'${mysqld_binary}' not found! Please re-install ${CATEGORY}/${PN}!"
630 local mysql_binary="${EROOT}/usr/bin/mysql"
631 if [[ ! -x "${mysql_binary}" ]] ; then
632 die "'${mysql_binary}' not found! Please re-install ${CATEGORY}/${PN}!"
635 local my_print_defaults_binary="${EROOT}/usr/bin/my_print_defaults"
636 if [[ ! -x "${my_print_defaults_binary}" ]] ; then
637 die "'${my_print_defaults_binary}' not found! Please re-install dev-db/mysql-connector-c!"
640 if [[ -z "${MYSQL_USER}" ]] ; then
643 MYSQL_USER=$(id -u -n 2>/dev/null)
644 if [[ -z "${MYSQL_USER}" ]] ; then
645 die "Failed to determine current username!"
650 if [[ -z "${MYSQL_GROUP}" ]] ; then
653 MYSQL_GROUP=$(id -g -n 2>/dev/null)
654 if [[ -z "${MYSQL_GROUP}" ]] ; then
655 die "Failed to determine current user groupname!"
660 # my_print_defaults needs to read stuff in $HOME/.my.cnf
661 local -x HOME="${EROOT}/root"
663 # Make sure the vars are correctly initialized
666 # Read currently set data directory
667 MY_DATADIR="$(_getoptval mysqld datadir "--defaults-file='${MY_SYSCONFDIR}/my.cnf'")"
669 # Bug #213475 - MySQL _will_ object strenously if your machine is named
670 # localhost. Also causes weird failures.
671 [[ "${HOSTNAME}" == "localhost" ]] && die "Your machine must NOT be named localhost"
673 if [[ -z "${MY_DATADIR}" ]] ; then
674 die "Sorry, unable to find MY_DATADIR!"
675 elif [[ -d "${MY_DATADIR}/mysql" ]] ; then
676 ewarn "Looks like your data directory '${MY_DATADIR}' is already initialized!"
677 ewarn "Please rename or delete its content if you wish to initialize a new data directory."
678 die "${PN} data directory at '${MY_DATADIR}' looks already initialized!"
681 MYSQL_TMPDIR="$(_getoptval mysqld tmpdir "--defaults-file='${MY_SYSCONFDIR}/my.cnf'")"
682 # These are dir+prefix
683 MYSQL_LOG_BIN="$(_getoptval mysqld log-bin "--defaults-file='${MY_SYSCONFDIR}/my.cnf'")"
684 MYSQL_LOG_BIN=${MYSQL_LOG_BIN%/*}
685 MYSQL_RELAY_LOG="$(_getoptval mysqld relay-log "--defaults-file='${MY_SYSCONFDIR}/my.cnf'")"
686 MYSQL_RELAY_LOG=${MYSQL_RELAY_LOG%/*}
688 # Create missing directories.
689 # Always check if mysql user can write to directory even if we just
690 # created directory because a parent directory might be not
691 # accessible for that user.
692 PID_DIR="${EROOT}/run/mysqld"
693 if [[ ! -d "${PID_DIR}" ]] ; then
694 einfo "Creating ${PN} PID directory '${PID_DIR}' ..."
695 install -d -m 755 -o ${MYSQL_USER} -g ${MYSQL_GROUP} "${PID_DIR}" \
696 || die "Failed to create PID directory '${PID_DIR}'!"
699 local _pid_dir_testfile="$(_mktemp_dry "${PID_DIR}/.pkg_config-access-test.XXXXXXXXX")"
700 [[ -z "${_pid_dir_testfile}" ]] \
701 && die "_mktemp_dry() for '${PID_DIR}/.pkg_config-access-test.XXXXXXXXX' failed!"
704 touch "${_pid_dir_testfile}" &>/dev/null
706 su -s /bin/sh -c "touch ${_pid_dir_testfile}" ${MYSQL_USER} &>/dev/null
709 if [[ $? -ne 0 ]] ; then
710 die "${MYSQL_USER} user cannot write into PID dir '${PID_DIR}'!"
712 rm "${_pid_dir_testfile}" || die
713 unset _pid_dir_testfile
716 if [[ ! -d "${MY_DATADIR}" ]] ; then
717 einfo "Creating ${PN} data directory '${MY_DATADIR}' ..."
718 install -d -m 770 -o ${MYSQL_USER} -g ${MYSQL_GROUP} "${MY_DATADIR}" \
719 || die "Failed to create ${PN} data directory '${MY_DATADIR}'!"
722 local _my_datadir_testfile="$(_mktemp_dry "${MY_DATADIR}/.pkg_config-access-test.XXXXXXXXX")"
723 [[ -z "${_my_datadir_testfile}" ]] \
724 && die "_mktemp_dry() for '${MY_DATADIR}/.pkg_config-access-test.XXXXXXXXX' failed!"
727 touch "${_my_datadir_testfile}" &>/dev/null
729 su -s /bin/sh -c "touch ${_my_datadir_testfile}" ${MYSQL_USER} &>/dev/null
732 if [[ $? -ne 0 ]] ; then
733 die "${MYSQL_USER} user cannot write into data directory '${MY_DATADIR}'!"
735 rm "${_my_datadir_testfile}" || die
736 unset _my_datadir_testfile
739 if [[ -n "${MYSQL_TMPDIR}" && ! -d "${MYSQL_TMPDIR}" ]] ; then
740 einfo "Creating ${PN} tmpdir '${MYSQL_TMPDIR}' ..."
741 install -d -m 770 -o ${MYSQL_USER} -g ${MYSQL_GROUP} "${MYSQL_TMPDIR}" \
742 || die "Failed to create ${PN} tmpdir '${MYSQL_TMPDIR}'!"
745 if [[ -z "${MYSQL_TMPDIR}" ]] ; then
746 MYSQL_TMPDIR="$(_mktemp_dry "${EROOT}/tmp/mysqld-tmp.XXXXXXXXX")"
747 [[ -z "${MYSQL_TMPDIR}" ]] \
748 && die "_mktemp_dry() for '${MYSQL_TMPDIR}' failed!"
750 mkdir "${MYSQL_TMPDIR}" || die
751 chown ${MYSQL_USER} "${MYSQL_TMPDIR}" || die
754 # Now we need to test MYSQL_TMPDIR...
755 local _my_tmpdir_testfile="$(_mktemp_dry "${MYSQL_TMPDIR}/.pkg_config-access-test.XXXXXXXXX")"
756 [[ -z "${_my_tmpdir_testfile}" ]] \
757 && die "_mktemp_dry() for '${MYSQL_TMPDIR}/.pkg_config-access-test.XXXXXXXXX' failed!"
760 touch "${_my_tmpdir_testfile}" &>/dev/null
762 su -s /bin/sh -c "touch ${_my_tmpdir_testfile}" ${MYSQL_USER} &>/dev/null
765 if [[ $? -ne 0 ]] ; then
766 die "${MYSQL_USER} user cannot write into tmpdir '${MYSQL_TMPDIR}'!"
768 rm "${_my_tmpdir_testfile}" || die
769 unset _my_tmpdir_testfile
772 if [[ -n "${MYSQL_LOG_BIN}" && ! -d "${MYSQL_LOG_BIN}" ]] ; then
773 einfo "Creating ${PN} log-bin directory '${MYSQL_LOG_BIN}' ..."
774 install -d -m 770 -o ${MYSQL_USER} -g ${MYSQL_GROUP} "${MYSQL_LOG_BIN}" \
775 || die "Failed to create ${PN} log-bin directory '${MYSQL_LOG_BIN}'"
778 if [[ -n "${MYSQL_LOG_BIN}" ]] ; then
779 local _my_logbin_testfile="$(_mktemp_dry "${MYSQL_LOG_BIN}/.pkg_config-access-test.XXXXXXXXX")"
780 [[ -z "${_my_logbin_testfile}" ]] \
781 && die "_mktemp_dry() for '${MYSQL_LOG_BIN}/.pkg_config-access-test.XXXXXXXXX' failed!"
784 touch "${_my_logbin_testfile}" &>/dev/null
786 su -s /bin/sh -c "touch ${_my_logbin_testfile}" ${MYSQL_USER} &>/dev/null
789 if [[ $? -ne 0 ]] ; then
790 die "${MYSQL_USER} user cannot write into log-bin directory '${MYSQL_LOG_BIN}'!"
792 rm "${_my_logbin_testfile}" || die
793 unset _my_logbin_testfile
797 if [[ -n "${MYSQL_RELAY_LOG}" && ! -d "${MYSQL_RELAY_LOG}" ]] ; then
798 einfo "Creating ${PN} relay-log directory '${MYSQL_RELAY_LOG}' ..."
799 install -d -m 770 -o ${MYSQL_USER} -g ${MYSQL_GROUP} "${MYSQL_RELAY_LOG}" \
800 || die "Failed to create ${PN} relay-log directory '${MYSQL_RELAY_LOG}'!"
803 if [[ -n "${MYSQL_RELAY_LOG}" ]] ; then
804 local _my_relaylog_testfile="$(_mktemp_dry "${MYSQL_RELAY_LOG}/.pkg_config-access-test.XXXXXXXXX")"
805 [[ -z "${_my_relaylog_testfile}" ]] \
806 && die "_mktemp_dry() for '${MYSQL_RELAY_LOG}/.pkg_config-access-test.XXXXXXXXX' failed!"
809 touch "${_my_relaylog_testfile}" &>/dev/null
811 su -s /bin/sh -c "touch ${_my_relaylog_testfile}" ${MYSQL_USER} &>/dev/null
814 if [[ $? -ne 0 ]] ; then
815 die "${MYSQL_USER} user cannot write into relay-log directory '${MYSQL_RELAY_LOG}'!"
817 rm "${_my_relaylog_testfile}" || die
818 unset _my_relaylog_testfile
822 local mysql_install_log="$(_mktemp_dry "${MYSQL_TMPDIR}/install_db.XXXXXXXXX.log")"
823 if [[ -z "${mysql_install_log}" ]] ; then
824 die "_mktemp_dry() for '${MYSQL_TMPDIR}/install_db.XXXXXXXXX.log' failed!"
826 # make sure file is writable for MYSQL_USER...
827 touch "${mysql_install_log}" || die
828 chown ${MYSQL_USER} "${mysql_install_log}" || die
831 local mysqld_logfile="$(_mktemp_dry "${MYSQL_TMPDIR}/install_mysqld.XXXXXXXXX.log")"
832 if [[ -z "${mysqld_logfile}" ]] ; then
833 die "_mktemp_dry() for '${MYSQL_TMPDIR}/install_mysqld.XXXXXXXXX.log' failed!"
835 # make sure file is writable for MYSQL_USER...
836 touch "${mysqld_logfile}" || die
837 chown ${MYSQL_USER} "${mysqld_logfile}" || die
841 einfo "Detected settings:"
842 einfo "=================="
843 einfo "MySQL User:\t\t\t\t${MYSQL_USER}"
844 einfo "MySQL Group:\t\t\t\t${MYSQL_GROUP}"
845 einfo "MySQL DATA directory:\t\t${MY_DATADIR}"
846 einfo "MySQL TMP directory:\t\t\t${MYSQL_TMPDIR}"
848 if [[ -n "${MYSQL_LOG_BIN}" ]] ; then
849 einfo "MySQL Binary Log File location:\t${MYSQL_LOG_BIN}"
852 if [[ -n "${MYSQL_RELAY_LOG}" ]] ; then
853 einfo "MySQL Relay Log File location:\t${MYSQL_RELAY_LOG}"
856 einfo "PID DIR:\t\t\t\t${PID_DIR}"
857 einfo "Install db log:\t\t\t${mysql_install_log}"
858 einfo "Install server log:\t\t\t${mysqld_logfile}"
860 local -a config_files
862 local config_file="${EROOT}/etc/mysql/mysql.d/50-distro-client.cnf"
863 if [[ -f "${config_file}" ]] ; then
864 config_files+=( "${config_file}" )
866 ewarn "Client configuration '${config_file}' not found; Skipping configuration of default authentication plugin for client ..."
869 config_file="${EROOT}/etc/mysql/mysql.d/50-distro-server.cnf"
870 if [[ -f "${config_file}" ]] ; then
871 config_files+=( "${config_file}" )
873 ewarn "Server configuration '${config_file}' not found; Skipping configuration of default authentication plugin for mysqld ..."
876 if [[ ${#config_files[@]} -gt 0 ]] ; then
877 if [[ -z "${MYSQL_DEFAULT_AUTHENTICATION_PLUGIN}" ]] ; then
881 einfo "Please select default authentication plugin (enter number or plugin name):"
882 einfo "1) caching_sha2_password [MySQL 8.0 default]"
883 einfo "2) mysql_native_password [MySQL 5.7 default]"
885 einfo "For details see:"
886 einfo "https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password"
887 read -p " >" user_answer
890 case "${user_answer}" in
891 1|caching_sha2_password)
892 MYSQL_DEFAULT_AUTHENTICATION_PLUGIN=caching_sha2_password
894 2|mysql_native_password)
895 MYSQL_DEFAULT_AUTHENTICATION_PLUGIN=mysql_native_password
898 die "No authentication plugin selected!"
901 die "Authentication plugin '${user_answer}' is unknown/unsupported!"
905 echo "Selected authentication plugin: ${MYSQL_DEFAULT_AUTHENTICATION_PLUGIN}" >> "${mysql_install_log}"
910 local cfg_option cfg_option_tabs cfg_section
911 for config_file in "${config_files[@]}" ; do
912 cfg_option="default-authentication-plugin"
914 cfg_option_tabs="\t\t"
915 if [[ "${config_file}" == *client.cnf ]] ; then
916 cfg_option="default-auth"
918 cfg_option_tabs="\t\t\t\t"
921 if grep -qE "^(loose-)?${cfg_option}\b.*=" "${config_file}" 2>/dev/null ; then
922 einfo "Ensuring that ${cfg_option} is set to '${MYSQL_DEFAULT_AUTHENTICATION_PLUGIN}' in '${config_file}' ..."
924 -e "s/^\(loose-\)\?${cfg_option}\b.*=.*/loose-${cfg_option}${cfg_option_tabs}= ${MYSQL_DEFAULT_AUTHENTICATION_PLUGIN}/" \
925 "${config_file}" || die "Failed to change ${cfg_option} in '${config_file}'!"
927 einfo "Setting ${cfg_option} to '${MYSQL_DEFAULT_AUTHENTICATION_PLUGIN}' in '${config_file}' ..."
929 -e "/^\[${cfg_section}\]$/a loose-${cfg_option}${cfg_option_tabs}= ${MYSQL_DEFAULT_AUTHENTICATION_PLUGIN}" \
930 "${config_file}" || die "Failed to add ${cfg_option} to '${config_file}'!"
933 unset cfg_option cfg_option_tabs cfg_section
935 unset config_files config_file
939 if [[ -z "${MYSQL_ROOT_PASSWORD}" ]] ; then
940 local tmp_mysqld_password_source=
942 for tmp_mysqld_password_source in mysql client ; do
943 einfo "Trying to get password for mysql 'root' user from '${tmp_mysqld_password_source}' section ..."
944 MYSQL_ROOT_PASSWORD="$(_getoptval "${tmp_mysqld_password_source}" password)"
945 if [[ -n "${MYSQL_ROOT_PASSWORD}" ]] ; then
946 if [[ ${MYSQL_ROOT_PASSWORD} == *$'\n'* ]] ; then
947 ewarn "Ignoring password from '${tmp_mysqld_password_source}' section due to newline character (do you have multiple password options set?)!"
952 einfo "Found password in '${tmp_mysqld_password_source}' section!"
957 # Sometimes --show is required to display passwords in some implementations of my_print_defaults
958 if [[ "${MYSQL_ROOT_PASSWORD}" == '*****' ]] ; then
959 MYSQL_ROOT_PASSWORD="$(_getoptval "${tmp_mysqld_password_source}" password --show)"
962 unset tmp_mysqld_password_source
965 if [[ -z "${MYSQL_ROOT_PASSWORD}" ]] ; then
970 einfo "No password for mysql 'root' user was specified via environment"
971 einfo "variable MYSQL_ROOT_PASSWORD and no password was found in config"
972 einfo "file like '${HOME}/.my.cnf'."
973 einfo "To continue please provide a password for the mysql 'root' user"
974 einfo "now on console:"
975 ewarn "NOTE: Please avoid [\"'\\_%] characters in the password!"
976 read -rsp " >" pwd1 ; echo
978 einfo "Retype the password"
979 read -rsp " >" pwd2 ; echo
981 if [[ "x$pwd1" != "x$pwd2" ]] ; then
982 die "Passwords are not the same!"
985 MYSQL_ROOT_PASSWORD="${pwd1}"
991 local -a mysqld_options
993 # Fix bug 446200. Don't reference host my.cnf, needs to come first,
994 # see http://bugs.mysql.com/bug.php?id=31312
995 use prefix && mysqld_options+=( "--defaults-file='${MY_SYSCONFDIR}/my.cnf'" )
997 # Figure out which options we need to disable to do the setup
998 local helpfile="${TMPDIR}/mysqld-help"
999 "${EROOT}/usr/sbin/mysqld" --verbose --help >"${helpfile}" 2>/dev/null
1001 local opt optexp optfull
1002 for opt in host-cache name-resolve networking slave-start \
1003 federated ssl log-bin relay-log slow-query-log external-locking \
1006 optexp="--(skip-)?${opt}" optfull="--loose-skip-${opt}"
1007 egrep -sq -- "${optexp}" "${helpfile}" && mysqld_options+=( "${optfull}" )
1010 # Prepare timezones, see
1011 # https://dev.mysql.com/doc/mysql/en/time-zone-support.html
1012 local tz_sql="$(_mktemp_dry "${MYSQL_TMPDIR}/tz.XXXXXXXXX.sql")"
1013 [[ -z "${tz_sql}" ]] \
1014 && die "_mktemp_dry() for '${MYSQL_TMPDIR}/tz.XXXXXXXXX.sql' failed!"
1016 echo "USE mysql;" >"${tz_sql}"
1017 "${EROOT}/usr/bin/mysql_tzinfo_to_sql" "${EROOT}/usr/share/zoneinfo" >> "${tz_sql}" 2>/dev/null
1018 if [[ $? -ne 0 ]] ; then
1019 die "mysql_tzinfo_to_sql failed!"
1022 # --initialize-insecure will not set root password
1023 # --initialize would set a random one in the log which we don't need as we set it ourselves
1026 "${mysqld_options[@]}"
1027 "--initialize-insecure"
1028 "--init-file='${tz_sql}'"
1029 "--basedir='${EROOT}/usr'"
1030 "--datadir='${MY_DATADIR}'"
1031 "--tmpdir='${MYSQL_TMPDIR}'"
1032 "--log-error='${mysql_install_log}'"
1033 "--user=${MYSQL_USER}"
1036 einfo "Initializing ${PN} data directory: ${cmd[@]}"
1037 eval "${cmd[@]}" >>"${mysql_install_log}" 2>&1
1039 if [[ $? -ne 0 || ! -f "${MY_DATADIR}/mysql.ibd" ]] ; then
1040 grep -B5 -A999 -iE "(Aborting|ERROR|errno)" "${mysql_install_log}" 1>&2
1041 die "Failed to initialize ${PN} data directory. Please review '${mysql_install_log}'!"
1044 rm "${tz_sql}" || die
1047 local socket="${EROOT}${PID_DIR}/mysqld${x}.sock"
1048 local pidfile="${EROOT}${PID_DIR}/mysqld${x}.pid"
1053 "${mysqld_options[@]}"
1054 "--basedir='${EROOT}/usr'"
1055 "--datadir='${MY_DATADIR}'"
1056 "--tmpdir='${MYSQL_TMPDIR}'"
1057 --max_allowed_packet=8M
1058 --net_buffer_length=16K
1059 "--socket='${socket}'"
1060 "--pid-file='${pidfile}'"
1061 "--log-error='${mysqld_logfile}'"
1062 "--user=${MYSQL_USER}"
1065 einfo "Starting mysqld to finalize initialization: ${cmd[@]}"
1066 eval "${cmd[@]}" >>"${mysqld_logfile}" 2>&1 &
1068 echo -n "Waiting for mysqld to accept connections "
1070 while [[ ! -S "${socket}" && "${maxtry}" -gt 1 ]] ; do
1071 maxtry=$((${maxtry}-1))
1076 if [[ -S "${socket}" ]] ; then
1077 # Even with a socket we don't know if mysqld will abort
1078 # start due to an error so just wait a little bit more...
1080 while [[ -S "${socket}" && "${maxtry}" -gt 1 ]] ; do
1081 maxtry=$((${maxtry}-1))
1089 if [[ ! -S "${socket}" ]] ; then
1090 grep -B5 -A999 -iE "(Aborting|ERROR|errno)" "${mysqld_logfile}" 1>&2
1091 die "mysqld was unable to start from initialized data directory. Please review '${mysqld_logfile}'!"
1094 local mysql_logfile="${TMPDIR}/set_root_pw.log"
1095 touch "${mysql_logfile}" || die
1097 ebegin "Setting root password"
1098 # Do this from memory, as we don't want clear text passwords in temp files
1099 local sql="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'"
1103 "--socket='${socket}'"
1107 eval "${cmd[@]}" >"${mysql_logfile}" 2>&1
1111 if [[ ${rc} -ne 0 ]] ; then
1112 # Poor man's solution which tries to avoid having password
1113 # in log. NOTE: sed can fail if user didn't follow advice
1114 # and included character which will require escaping...
1115 sed -i -e "s/${MYSQL_ROOT_PASSWORD}/*****/" "${mysql_logfile}" 2>/dev/null
1117 grep -B5 -A999 -iE "(Aborting|ERROR|errno)" "${mysql_logfile}"
1118 die "Failed to set ${PN} root password. Please review '${mysql_logfile}'!"
1122 if [[ -f "${pidfile}" ]] && pgrep -F "${pidfile}" &>/dev/null ; then
1123 echo -n "Stopping the server "
1124 pkill -F "${pidfile}" &>/dev/null
1127 while [[ -f "${pidfile}" ]] && pgrep -F "${pidfile}" &>/dev/null ; do
1128 maxtry=$((${maxtry}-1))
1135 if [[ -f "${pidfile}" ]] && pgrep -F "${pidfile}" &>/dev/null ; then
1136 # We somehow failed to stop server.
1137 # However, not a fatal error. Just warn the user.
1138 ewarn "WARNING: mysqld[$(cat "${pidfile}")] is still running!"
1142 einfo "${PN} data directory at '${MY_DATADIR}' successfully initialized!"