fix: avoid admin credential prompt on fresh mariadb install

This commit is contained in:
Sora39831 2026-04-22 10:10:04 +08:00
parent fa73367e7e
commit 326abb3a44
4 changed files with 158 additions and 12 deletions

View file

@ -0,0 +1,51 @@
Task Record:
Date: 2026-04-22
Related Module: MariaDB admin auth in installer and menu script
Change Type: Fix
Background
During local MariaDB setup, when socket auth failed the script asked for admin credentials.
On hosts where admin/root password is empty, the previous command construction always appended `-p`, which can cause authentication checks to fail for empty-password accounts.
This led to false "管理员账号连接失败" and blocked install/uninstall flows.
Changes
Updated MariaDB connection execution in both `install.sh` and `x-ui.sh`:
- Build MariaDB client command with optional password flag.
- Append `-p<password>` only when password is non-empty.
- Apply this to server-connection check, database-connection check, and admin SQL execution.
- Prompt text updated to indicate admin password can be empty.
- Added retry logic (up to 10 seconds) before declaring socket auth failure.
- Added automatic fallback to `root@127.0.0.1` with empty password before prompting admin credentials.
- For freshly installed local MariaDB in script flow, set an install marker and prefer non-interactive auto init path.
Added `tests/mariadb_admin_empty_password_test.sh` for static regression checks.
Impact
Affected files:
- `install.sh`
- `x-ui.sh`
- `tests/mariadb_admin_empty_password_test.sh`
No API/database schema change.
Install, DB switching, and uninstall paths are more compatible with empty-password admin setups.
Verification
Commands:
- `bash -n install.sh`
- `bash -n x-ui.sh`
- `bash tests/mariadb_admin_empty_password_test.sh`
- `bash tests/install_uninstall_resilience_test.sh`
- `bash tests/panel_port_prompt_test.sh`
- `bash tests/mariadb_install_switch_test.sh`
Result:
- All checks passed.
Risks And Follow-Up
Current tests are static assertions. Full runtime verification still depends on real MariaDB environment variants (socket auth, TCP auth, empty password, root-password mode).

View file

@ -222,6 +222,7 @@ ensure_mariadb_client_ready() {
ensure_local_mariadb_ready() {
if ! has_local_mariadb_service; then
install_local_mariadb_server || return 1
LOCAL_MARIADB_JUST_INSTALLED="1"
fi
ensure_mariadb_client_ready || return 1
start_mariadb_service || true
@ -231,15 +232,27 @@ ensure_local_mariadb_ready() {
test_mariadb_server_connection() {
local host="$1" port="$2" user="$3" pass="$4"
local bin
local -a cmd
bin=$(mariadb_cli_bin) || return 1
"$bin" -h "$host" -P "$port" -u "$user" -p"$pass" -e "SELECT 1;" >/dev/null 2>&1
cmd=("$bin" -h "$host" -P "$port" -u "$user")
if [[ -n "$pass" ]]; then
cmd+=("-p$pass")
fi
cmd+=(-e "SELECT 1;")
"${cmd[@]}" >/dev/null 2>&1
}
test_mariadb_database_connection() {
local host="$1" port="$2" dbname="$3" user="$4" pass="$5"
local bin
local -a cmd
bin=$(mariadb_cli_bin) || return 1
"$bin" -h "$host" -P "$port" -u "$user" -p"$pass" -D "$dbname" -e "SELECT 1;" >/dev/null 2>&1
cmd=("$bin" -h "$host" -P "$port" -u "$user" -D "$dbname")
if [[ -n "$pass" ]]; then
cmd+=("-p$pass")
fi
cmd+=(-e "SELECT 1;")
"${cmd[@]}" >/dev/null 2>&1
}
is_safe_mariadb_identifier() {
@ -254,6 +267,7 @@ LOCAL_MARIADB_ADMIN_MODE=""
LOCAL_MARIADB_ADMIN_USER=""
LOCAL_MARIADB_ADMIN_PASS=""
LOCAL_MARIADB_ADMIN_PORT="3306"
LOCAL_MARIADB_JUST_INSTALLED="0"
try_local_mariadb_socket_admin() {
local bin
@ -263,10 +277,26 @@ try_local_mariadb_socket_admin() {
ensure_local_mariadb_admin_access() {
local port="${1:-3306}"
local i
LOCAL_MARIADB_ADMIN_PORT="$port"
if try_local_mariadb_socket_admin; then
LOCAL_MARIADB_ADMIN_MODE="socket"
# Fresh installs may need a few seconds before local socket auth is ready.
for ((i = 0; i < 10; i++)); do
if try_local_mariadb_socket_admin; then
LOCAL_MARIADB_ADMIN_MODE="socket"
return 0
fi
sleep 1
done
# Common default on fresh installs: root can connect via TCP without password.
if test_mariadb_server_connection "127.0.0.1" "$port" "root" ""; then
LOCAL_MARIADB_ADMIN_MODE="password"
LOCAL_MARIADB_ADMIN_USER="root"
LOCAL_MARIADB_ADMIN_PASS=""
if [[ "$LOCAL_MARIADB_JUST_INSTALLED" == "1" ]]; then
echo -e "${green}检测到新安装 MariaDB已自动使用 root 免密权限初始化数据库。${plain}"
fi
return 0
fi
@ -274,7 +304,7 @@ ensure_local_mariadb_admin_access() {
echo -e "${yellow}无法通过 root socket 直接连接本地 MariaDB请输入管理员账号信息。${plain}"
read -rp "MariaDB 管理员用户名 [root]: " admin_user
admin_user="${admin_user:-root}"
read -rsp "MariaDB 管理员密码: " admin_pass
read -rsp "MariaDB 管理员密码(可留空): " admin_pass
echo
if ! test_mariadb_server_connection "127.0.0.1" "$port" "$admin_user" "$admin_pass"; then
@ -290,6 +320,7 @@ ensure_local_mariadb_admin_access() {
run_local_mariadb_admin_sql() {
local sql="$1"
local bin
local -a cmd
bin=$(mariadb_cli_bin) || return 1
case "$LOCAL_MARIADB_ADMIN_MODE" in
@ -297,7 +328,12 @@ run_local_mariadb_admin_sql() {
"$bin" -e "$sql" >/dev/null 2>&1 || "$bin" -uroot -e "$sql" >/dev/null 2>&1
;;
password)
"$bin" -h "127.0.0.1" -P "$LOCAL_MARIADB_ADMIN_PORT" -u "$LOCAL_MARIADB_ADMIN_USER" -p"$LOCAL_MARIADB_ADMIN_PASS" -e "$sql" >/dev/null 2>&1
cmd=("$bin" -h "127.0.0.1" -P "$LOCAL_MARIADB_ADMIN_PORT" -u "$LOCAL_MARIADB_ADMIN_USER")
if [[ -n "$LOCAL_MARIADB_ADMIN_PASS" ]]; then
cmd+=("-p$LOCAL_MARIADB_ADMIN_PASS")
fi
cmd+=(-e "$sql")
"${cmd[@]}" >/dev/null 2>&1
;;
*)
return 1

View file

@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
assert_contains() {
local file="$1"
local pattern="$2"
if ! grep -Fq "$pattern" "$file"; then
echo "missing pattern in $file: $pattern" >&2
return 1
fi
}
assert_contains "install.sh" "MariaDB 管理员密码(可留空)"
assert_contains "install.sh" "if [[ -n \"\$pass\" ]]; then"
assert_contains "install.sh" "if [[ -n \"\$LOCAL_MARIADB_ADMIN_PASS\" ]]; then"
assert_contains "install.sh" "test_mariadb_server_connection \"127.0.0.1\" \"\$port\" \"root\" \"\""
assert_contains "install.sh" "LOCAL_MARIADB_JUST_INSTALLED=\"1\""
assert_contains "x-ui.sh" "MariaDB 管理员密码(可留空)"
assert_contains "x-ui.sh" "if [[ -n \"\$pass\" ]]; then"
assert_contains "x-ui.sh" "if [[ -n \"\$LOCAL_MARIADB_ADMIN_PASS\" ]]; then"
assert_contains "x-ui.sh" "test_mariadb_server_connection \"127.0.0.1\" \"\$port\" \"root\" \"\""
assert_contains "x-ui.sh" "LOCAL_MARIADB_JUST_INSTALLED=\"1\""
echo "mariadb admin empty-password flow looks correct"

46
x-ui.sh
View file

@ -2655,6 +2655,7 @@ ensure_local_mariadb_ready() {
echo -e "${yellow}未检测到本地 MariaDB 服务${plain}"
confirm "是否安装本地 MariaDB" "y" || return 1
install_local_mariadb_server || return 1
LOCAL_MARIADB_JUST_INSTALLED="1"
fi
ensure_mariadb_client_ready || return 1
start_mariadb_service || true
@ -2664,15 +2665,27 @@ ensure_local_mariadb_ready() {
test_mariadb_server_connection() {
local host="$1" port="$2" user="$3" pass="$4"
local bin
local -a cmd
bin=$(mariadb_cli_bin) || return 1
"$bin" -h "$host" -P "$port" -u "$user" -p"$pass" -e "SELECT 1;" >/dev/null 2>&1
cmd=("$bin" -h "$host" -P "$port" -u "$user")
if [[ -n "$pass" ]]; then
cmd+=("-p$pass")
fi
cmd+=(-e "SELECT 1;")
"${cmd[@]}" >/dev/null 2>&1
}
test_mariadb_database_connection() {
local host="$1" port="$2" dbname="$3" user="$4" pass="$5"
local bin
local -a cmd
bin=$(mariadb_cli_bin) || return 1
"$bin" -h "$host" -P "$port" -u "$user" -p"$pass" -D "$dbname" -e "SELECT 1;" >/dev/null 2>&1
cmd=("$bin" -h "$host" -P "$port" -u "$user" -D "$dbname")
if [[ -n "$pass" ]]; then
cmd+=("-p$pass")
fi
cmd+=(-e "SELECT 1;")
"${cmd[@]}" >/dev/null 2>&1
}
is_safe_mariadb_identifier() {
@ -2687,6 +2700,7 @@ LOCAL_MARIADB_ADMIN_MODE=""
LOCAL_MARIADB_ADMIN_USER=""
LOCAL_MARIADB_ADMIN_PASS=""
LOCAL_MARIADB_ADMIN_PORT="3306"
LOCAL_MARIADB_JUST_INSTALLED="0"
try_local_mariadb_socket_admin() {
local bin
@ -2696,10 +2710,24 @@ try_local_mariadb_socket_admin() {
ensure_local_mariadb_admin_access() {
local port="${1:-3306}"
local i
LOCAL_MARIADB_ADMIN_PORT="$port"
if try_local_mariadb_socket_admin; then
LOCAL_MARIADB_ADMIN_MODE="socket"
for ((i = 0; i < 10; i++)); do
if try_local_mariadb_socket_admin; then
LOCAL_MARIADB_ADMIN_MODE="socket"
return 0
fi
sleep 1
done
if test_mariadb_server_connection "127.0.0.1" "$port" "root" ""; then
LOCAL_MARIADB_ADMIN_MODE="password"
LOCAL_MARIADB_ADMIN_USER="root"
LOCAL_MARIADB_ADMIN_PASS=""
if [[ "$LOCAL_MARIADB_JUST_INSTALLED" == "1" ]]; then
echo -e "${green}检测到新安装 MariaDB已自动使用 root 免密权限初始化数据库。${plain}"
fi
return 0
fi
@ -2707,7 +2735,7 @@ ensure_local_mariadb_admin_access() {
echo -e "${yellow}无法通过 root socket 直接连接本地 MariaDB请输入管理员账号信息。${plain}"
read -rp "MariaDB 管理员用户名 [root]: " admin_user
admin_user="${admin_user:-root}"
read -rsp "MariaDB 管理员密码: " admin_pass
read -rsp "MariaDB 管理员密码(可留空): " admin_pass
echo
if ! test_mariadb_server_connection "127.0.0.1" "$port" "$admin_user" "$admin_pass"; then
@ -2723,6 +2751,7 @@ ensure_local_mariadb_admin_access() {
run_local_mariadb_admin_sql() {
local sql="$1"
local bin
local -a cmd
bin=$(mariadb_cli_bin) || return 1
case "$LOCAL_MARIADB_ADMIN_MODE" in
@ -2730,7 +2759,12 @@ run_local_mariadb_admin_sql() {
"$bin" -e "$sql" >/dev/null 2>&1 || "$bin" -uroot -e "$sql" >/dev/null 2>&1
;;
password)
"$bin" -h "127.0.0.1" -P "$LOCAL_MARIADB_ADMIN_PORT" -u "$LOCAL_MARIADB_ADMIN_USER" -p"$LOCAL_MARIADB_ADMIN_PASS" -e "$sql" >/dev/null 2>&1
cmd=("$bin" -h "127.0.0.1" -P "$LOCAL_MARIADB_ADMIN_PORT" -u "$LOCAL_MARIADB_ADMIN_USER")
if [[ -n "$LOCAL_MARIADB_ADMIN_PASS" ]]; then
cmd+=("-p$LOCAL_MARIADB_ADMIN_PASS")
fi
cmd+=(-e "$sql")
"${cmd[@]}" >/dev/null 2>&1
;;
*)
return 1