125 lines
4.3 KiB
Bash
125 lines
4.3 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
if [ "$(id -u)" = "0" ]; then
|
|
echo "Switching to dedicated user 'mysql'"
|
|
exec gosu mysql "$BASH_SOURCE" "$@"
|
|
fi
|
|
|
|
# usage: file_env VAR [DEFAULT]
|
|
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
|
|
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
|
|
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
|
|
file_env() {
|
|
local var="$1"
|
|
local fileVar="${var}_FILE"
|
|
local def="${2:-}"
|
|
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
|
|
mysql_error "Both $var and $fileVar are set (but are exclusive)"
|
|
fi
|
|
local val="$def"
|
|
if [ "${!var:-}" ]; then
|
|
val="${!var}"
|
|
elif [ "${!fileVar:-}" ]; then
|
|
val="$(< "${!fileVar}")"
|
|
fi
|
|
export "$var"="$val"
|
|
unset "$fileVar"
|
|
}
|
|
|
|
# set MARIADB_xyz from MYSQL_xyz when MARIADB_xyz is unset
|
|
# and make them the same value (so user scripts can use either)
|
|
_mariadb_file_env() {
|
|
local var="$1"; shift
|
|
local maria="MARIADB_${var#MYSQL_}"
|
|
file_env "$var" "$@"
|
|
file_env "$maria" "${!var}"
|
|
if [ "${!maria:-}" ]; then
|
|
export "$var"="${!maria}"
|
|
fi
|
|
}
|
|
|
|
# SQL escape the string $1 to be placed in a string literal.
|
|
# escape, \ followed by '
|
|
docker_sql_escape_string_literal() {
|
|
local newline=$'\n'
|
|
local escaped=${1//\\/\\\\}
|
|
escaped="${escaped//$newline/\\n}"
|
|
echo "${escaped//\'/\\\'}"
|
|
}
|
|
|
|
mysql_get_config() {
|
|
local conf="$1"; shift
|
|
mysqld --verbose --help 2>/dev/null \
|
|
| awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
|
|
}
|
|
|
|
# Build env vars
|
|
DATADIR="$(mysql_get_config 'datadir')"
|
|
SOCKET="$(mysql_get_config 'socket')"
|
|
|
|
_mariadb_file_env 'MYSQL_ROOT_HOST' '%'
|
|
_mariadb_file_env 'MYSQL_ROOT_PASSWORD'
|
|
|
|
: "${MARIADB_ALLOW_EMPTY_ROOT_PASSWORD:=${MYSQL_ALLOW_EMPTY_PASSWORD:-}}"
|
|
export MYSQL_ALLOW_EMPTY_PASSWORD="$MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" MARIADB_ALLOW_EMPTY_ROOT_PASSWORD
|
|
: "${MARIADB_RANDOM_ROOT_PASSWORD:=${MYSQL_RANDOM_ROOT_PASSWORD:-}}"
|
|
export MYSQL_RANDOM_ROOT_PASSWORD="$MARIADB_RANDOM_ROOT_PASSWORD" MARIADB_RANDOM_ROOT_PASSWORD
|
|
: "${MARIADB_INITDB_SKIP_TZINFO:=${MYSQL_INITDB_SKIP_TZINFO:-}}"
|
|
export MYSQL_INITDB_SKIP_TZINFO="$MARIADB_INITDB_SKIP_TZINFO" MARIADB_INITDB_SKIP_TZINFO
|
|
|
|
if [ -z "$MARIADB_ROOT_PASSWORD" -a -z "$MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" -a -z "$MARIADB_RANDOM_ROOT_PASSWORD" ]; then
|
|
mysql_error $'Database is uninitialized and password option is not specified\n\tYou need to specify one of MARIADB_ROOT_PASSWORD, MARIADB_ALLOW_EMPTY_ROOT_PASSWORD and MARIADB_RANDOM_ROOT_PASSWORD'
|
|
fi
|
|
|
|
# Spin up temp server
|
|
echo "Starting temporary MariaDB server..."
|
|
|
|
mysqld --skip-networking --skip-grant-tables --socket="${SOCKET}" &
|
|
|
|
echo "Waiting for server startup"
|
|
for i in {30..0}; do
|
|
if mysql --protocol=socket -hlocalhost -uroot --socket="${SOCKET}" --database=mysql <<<'SELECT 1'; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
if [ "$i" = 0 ]; then
|
|
echo "Unable to start temporary server."
|
|
exit 1
|
|
fi
|
|
|
|
# Try password reset
|
|
echo "Resetting root password..."
|
|
|
|
if [ -n "$MARIADB_RANDOM_ROOT_PASSWORD" ]; then
|
|
MARIADB_ROOT_PASSWORD="$(pwgen --numerals --capitalize --symbols --remove-chars="'\\" -1 32)"
|
|
export MARIADB_ROOT_PASSWORD MYSQL_ROOT_PASSWORD=$MARIADB_ROOT_PASSWORD
|
|
echo "GENERATED ROOT PASSWORD: $MARIADB_ROOT_PASSWORD"
|
|
fi
|
|
|
|
# Sets root password and creates root users for non-localhost hosts
|
|
rootCreate=
|
|
rootPasswordEscaped=$( docker_sql_escape_string_literal "${MARIADB_ROOT_PASSWORD}" )
|
|
|
|
# default root to listen for connections from anywhere
|
|
if [ -n "$MARIADB_ROOT_HOST" ] && [ "$MARIADB_ROOT_HOST" != 'localhost' ]; then
|
|
# no, we don't care if read finds a terminating character in this heredoc
|
|
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
|
|
read -r -d '' rootCreate <<-EOSQL || true
|
|
ALTER USER 'root'@'${MARIADB_ROOT_HOST}' IDENTIFIED BY '${rootPasswordEscaped}' ;
|
|
GRANT ALL ON *.* TO 'root'@'${MARIADB_ROOT_HOST}' WITH GRANT OPTION ;
|
|
EOSQL
|
|
fi
|
|
|
|
# tell docker_process_sql to not use MARIADB_ROOT_PASSWORD since it is just now being set
|
|
# --binary-mode to save us from the semi-mad users go out of their way to confuse the encoding.
|
|
mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" --database=mysql --binary-mode <<-EOSQL
|
|
FLUSH PRIVILEGES ;
|
|
ALTER USER 'root'@'localhost' IDENTIFIED BY '${rootPasswordEscaped}' ;
|
|
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
|
|
|
|
${rootCreate}
|
|
EOSQL
|
|
|
|
echo "Password reset complete."
|