合并账户库为单表

This commit is contained in:
wkc
2026-04-17 10:18:13 +08:00
parent cc1a4538af
commit 4c6ca52e7e
24 changed files with 1285 additions and 377 deletions

101
deploy/deploy-to-nas-tongweb.sh Executable file
View File

@@ -0,0 +1,101 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
SERVER_HOST="116.62.17.81"
SERVER_PORT="9444"
SERVER_USERNAME="wkc"
SERVER_PASSWORD="wkc@0825"
REMOTE_ROOT="/volume1/webapp/ccdi"
TONGWEB_HOME="${TONGWEB_HOME:-/opt/TongWeb}"
APP_NAME="${APP_NAME:-ruoyi-admin}"
DRY_RUN="false"
ensure_command() {
local command_name="$1"
if ! command -v "${command_name}" >/dev/null 2>&1; then
echo "缺少命令: ${command_name}" >&2
exit 1
fi
}
ensure_paramiko() {
if python3 - <<'PY'
import importlib.util
import sys
sys.exit(0 if importlib.util.find_spec("paramiko") else 1)
PY
then
return
fi
python3 -m pip install --user paramiko
}
POSITION=0
for arg in "$@"; do
if [[ "${arg}" == "--dry-run" ]]; then
DRY_RUN="true"
continue
fi
POSITION=$((POSITION + 1))
case "${POSITION}" in
1) SERVER_HOST="${arg}" ;;
2) SERVER_PORT="${arg}" ;;
3) SERVER_USERNAME="${arg}" ;;
4) SERVER_PASSWORD="${arg}" ;;
5) REMOTE_ROOT="${arg}" ;;
6) TONGWEB_HOME="${arg}" ;;
7) APP_NAME="${arg}" ;;
*)
echo "仅支持 [host] [port] [username] [password] [remoteRoot] [tongwebHome] [appName] [--dry-run]" >&2
exit 1
;;
esac
done
if [[ "${DRY_RUN}" == "true" ]]; then
echo "[DryRun] TongWeb NAS 部署参数预览"
echo "Host: ${SERVER_HOST}"
echo "Port: ${SERVER_PORT}"
echo "Username: ${SERVER_USERNAME}"
echo "RemoteRoot: ${REMOTE_ROOT}"
echo "TongWebHome: ${TONGWEB_HOME}"
echo "AppName: ${APP_NAME}"
exit 0
fi
echo "[1/4] 检查本地环境"
ensure_command "mvn"
ensure_command "python3"
echo "[2/4] 打包后端 war"
(
cd "${REPO_ROOT}"
mvn -pl ruoyi-admin -am package -DskipTests
)
WAR_PATH="${REPO_ROOT}/ruoyi-admin/target/ruoyi-admin.war"
if [[ ! -f "${WAR_PATH}" ]]; then
echo "未找到后端 war 包: ${WAR_PATH}" >&2
exit 1
fi
echo "[3/4] 检查远端执行依赖"
ensure_paramiko
echo "[4/4] 上传 war 并重启 TongWeb"
python3 "${SCRIPT_DIR}/remote-deploy-tongweb.py" \
--host "${SERVER_HOST}" \
--port "${SERVER_PORT}" \
--username "${SERVER_USERNAME}" \
--password "${SERVER_PASSWORD}" \
--local-war "${WAR_PATH}" \
--remote-root "${REMOTE_ROOT}" \
--tongweb-home "${TONGWEB_HOME}" \
--app-name "${APP_NAME}"

View File

@@ -0,0 +1,136 @@
import argparse
import posixpath
import shlex
import sys
from pathlib import Path
import paramiko
def parse_args():
parser = argparse.ArgumentParser(description="Upload backend war to NAS and restart TongWeb.")
parser.add_argument("--host", required=True)
parser.add_argument("--port", type=int, required=True)
parser.add_argument("--username", required=True)
parser.add_argument("--password", required=True)
parser.add_argument("--local-war", required=True)
parser.add_argument("--remote-root", required=True)
parser.add_argument("--tongweb-home", required=True)
parser.add_argument("--app-name", required=True)
return parser.parse_args()
def run_command(ssh, command):
stdin, stdout, stderr = ssh.exec_command(command)
exit_code = stdout.channel.recv_exit_status()
output = stdout.read().decode("utf-8", errors="ignore")
error = stderr.read().decode("utf-8", errors="ignore")
return exit_code, output, error
def sudo_prefix(password):
return f"printf '%s\\n' {shlex.quote(password)} | sudo -S -p '' "
def detect_command_prefix(ssh, password, command):
plain_exit_code, _, _ = run_command(ssh, f"{command} >/dev/null 2>&1")
if plain_exit_code == 0:
return ""
sudo_probe = f"{sudo_prefix(password)}{command} >/dev/null 2>&1"
sudo_exit_code, _, _ = run_command(ssh, sudo_probe)
if sudo_exit_code == 0:
return sudo_prefix(password)
raise RuntimeError(f"Remote command is not accessible: {command}")
def ensure_remote_path(ssh, prefix, remote_path):
command = f"{prefix}mkdir -p {shlex.quote(remote_path)}"
exit_code, output, error = run_command(ssh, command)
if exit_code != 0:
raise RuntimeError(f"Failed to create remote directory {remote_path}:\n{output}\n{error}")
def upload_file(sftp, local_file, remote_file):
parent_dir = posixpath.dirname(remote_file)
try:
sftp.listdir(parent_dir)
except OSError:
raise RuntimeError(f"SFTP remote directory not found: {parent_dir}")
sftp.put(str(local_file), remote_file)
def build_deploy_command(args, prefix):
app_war_name = f"{args.app_name}.war"
remote_war_path = posixpath.join(args.remote_root.rstrip("/"), "backend", app_war_name)
autodeploy_dir = posixpath.join(args.tongweb_home.rstrip("/"), "autodeploy")
deployed_war_path = posixpath.join(autodeploy_dir, app_war_name)
deployed_dir_path = posixpath.join(autodeploy_dir, args.app_name)
stop_script = posixpath.join(args.tongweb_home.rstrip("/"), "bin", "stopserver.sh")
start_script = posixpath.join(args.tongweb_home.rstrip("/"), "bin", "startservernohup.sh")
return (
"set -e;"
f"test -d {shlex.quote(args.tongweb_home)};"
f"test -x {shlex.quote(stop_script)};"
f"test -x {shlex.quote(start_script)};"
f"{prefix}mkdir -p {shlex.quote(autodeploy_dir)};"
f"{prefix}sh {shlex.quote(stop_script)} >/dev/null 2>&1 || true;"
f"{prefix}rm -rf {shlex.quote(deployed_dir_path)};"
f"{prefix}rm -f {shlex.quote(deployed_war_path)};"
f"{prefix}cp {shlex.quote(remote_war_path)} {shlex.quote(deployed_war_path)};"
f"{prefix}sh {shlex.quote(start_script)};"
"sleep 5;"
f"ls -l {shlex.quote(autodeploy_dir)};"
)
def main():
args = parse_args()
local_war = Path(args.local_war).resolve()
if not local_war.exists():
raise FileNotFoundError(f"Local war does not exist: {local_war}")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(
hostname=args.host,
port=args.port,
username=args.username,
password=args.password,
timeout=20,
)
sftp = ssh.open_sftp()
try:
remote_root = args.remote_root.rstrip("/")
remote_backend_dir = posixpath.join(remote_root, "backend")
remote_war_path = posixpath.join(remote_backend_dir, f"{args.app_name}.war")
ensure_remote_path(ssh, "", remote_root)
ensure_remote_path(ssh, "", remote_backend_dir)
upload_file(sftp, local_war, remote_war_path)
command_prefix = detect_command_prefix(ssh, args.password, f"test -d {shlex.quote(args.tongweb_home)}")
deploy_command = build_deploy_command(args, command_prefix)
exit_code, output, error = run_command(ssh, deploy_command)
if exit_code != 0:
raise RuntimeError(f"Remote TongWeb deploy failed:\n{output}\n{error}")
print("=== DEPLOY OUTPUT ===")
print(output.strip())
if error.strip():
print("=== DEPLOY STDERR ===")
print(error.strip())
finally:
sftp.close()
ssh.close()
if __name__ == "__main__":
try:
main()
except Exception as exc:
print(str(exc), file=sys.stderr)
sys.exit(1)