release: nexus btpanel session fix and app-v2

This commit is contained in:
Codex Release Bot
2026-07-08 22:31:31 +08:00
commit 1933f0af6e
2457 changed files with 350105 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
#!/usr/bin/env bash
# Nexus — MySQL dumpDocker 1Panel / 宿主机 mysqldump 通用)
#
# bash deploy/mysql_dump_to_file.sh --output /path/dump.sql [--root /opt/nexus]
# bash deploy/mysql_dump_to_file.sh --output /path/dump.sql --db-url 'mysql+aiomysql://...'
#
# 策略(按序):
# 1. DB host 为运行中容器名 → docker exec 该容器内 mysqldump(连 127.0.0.1
# 2. 宿主机有 mysqldump 且 host 可解析 → 本机 mysqldump
# 3. 1panel-network 存在 → docker run --rm mysql:8 客户端
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
NEXUS_ROOT="${NEXUS_ROOT:-/opt/nexus}"
OUTPUT=""
DB_URL=""
usage() {
cat <<'EOF'
用法: mysql_dump_to_file.sh --output FILE.sql [--root /opt/nexus] [--db-url URL]
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--output|-o) OUTPUT="$2"; shift 2 ;;
--root) NEXUS_ROOT="$2"; shift 2 ;;
--db-url) DB_URL="$2"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) echo "未知参数: $1" >&2; usage; exit 1 ;;
esac
done
if [[ -z "$OUTPUT" ]]; then
echo "缺少 --output" >&2
usage
exit 1
fi
resolve_db_url() {
if [[ -n "$DB_URL" ]]; then
echo "$DB_URL"
return 0
fi
local cname url
cname="$(docker ps --format '{{.Names}}' 2>/dev/null | grep -E 'nexus-prod-nexus|nexus-nexus-1' | head -1 || true)"
if [[ -n "$cname" ]]; then
url="$(docker exec "$cname" grep -E '^NEXUS_DATABASE_URL=' /app/.env 2>/dev/null | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'" || true)"
[[ -n "$url" ]] && echo "$url" && return 0
fi
for f in \
"${NEXUS_ROOT}/docker/.env.prod" \
"${NEXUS_ROOT}/.env" \
; do
[[ -f "$f" ]] || continue
url="$(grep -E '^NEXUS_DATABASE_URL=' "$f" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'" || true)"
[[ -n "$url" ]] && echo "$url" && return 0
done
return 1
}
DB_URL="$(resolve_db_url || true)"
if [[ -z "$DB_URL" ]]; then
echo "未找到 NEXUS_DATABASE_URL" >&2
exit 1
fi
python3 - "$DB_URL" "$OUTPUT" <<'PY'
import shutil
import subprocess
import sys
import urllib.parse
def docker_names() -> set[str]:
r = subprocess.run(
["docker", "ps", "--format", "{{.Names}}"],
capture_output=True,
text=True,
check=False,
)
return {ln.strip() for ln in (r.stdout or "").splitlines() if ln.strip()}
def network_exists(name: str) -> bool:
return (
subprocess.run(
["docker", "network", "inspect", name],
capture_output=True,
check=False,
).returncode
== 0
)
def write_dump(cmd: list[str], env: dict[str, str], out: str) -> int:
r = subprocess.run(cmd, env=env, capture_output=True, text=True)
if r.returncode != 0:
sys.stderr.write(r.stderr or r.stdout or "mysqldump failed\n")
return r.returncode
with open(out, "w", encoding="utf-8") as fh:
fh.write(r.stdout)
return 0
def dump_flags(db: str) -> list[str]:
return [
"--single-transaction",
"--routines",
"--triggers",
"--set-gtid-purged=OFF",
db,
]
url = sys.argv[1].replace("mysql+aiomysql://", "mysql://", 1)
url = url.replace("mysql+asyncmy://", "mysql://", 1)
out = sys.argv[2]
p = urllib.parse.urlparse(url)
user = urllib.parse.unquote(p.username or "")
password = urllib.parse.unquote(p.password or "")
host = p.hostname or "127.0.0.1"
if host == "host.docker.internal":
host = "127.0.0.1"
port = str(p.port or 3306)
db = (p.path or "/nexus").lstrip("/").split("?")[0]
env = {**__import__("os").environ, "MYSQL_PWD": password}
names = docker_names()
# 1) MySQL 跑在 Docker 容器内(1Panel 常见:URL host = 容器名)
if host in names:
cmd = [
"docker",
"exec",
"-e",
f"MYSQL_PWD={password}",
host,
"mysqldump",
"-h",
"127.0.0.1",
"-P",
port,
"-u",
user,
*dump_flags(db),
]
rc = write_dump(cmd, env, out)
if rc == 0:
sys.exit(0)
sys.stderr.write(f"docker exec {host} mysqldump 失败,尝试其它方式…\n")
# 2) 宿主机 mysqldump
if shutil.which("mysqldump"):
cmd = [
"mysqldump",
"-h",
host,
"-P",
port,
"-u",
user,
*dump_flags(db),
]
rc = write_dump(cmd, env, out)
if rc == 0:
sys.exit(0)
# 3) 临时 mysql 客户端容器(1panel-network
for net in ("1panel-network", "bridge"):
if not network_exists(net):
continue
cmd = [
"docker",
"run",
"--rm",
"--network",
net,
"-e",
f"MYSQL_PWD={password}",
"mysql:8.0",
"mysqldump",
"-h",
host,
"-P",
port,
"-u",
user,
*dump_flags(db),
]
rc = write_dump(cmd, env, out)
if rc == 0:
sys.exit(0)
sys.stderr.write("所有 mysqldump 策略均失败(无宿主机客户端且 Docker 回退不可用)\n")
sys.exit(1)
PY