合并账户库为单表
This commit is contained in:
101
deploy/deploy-to-nas-tongweb.sh
Executable file
101
deploy/deploy-to-nas-tongweb.sh
Executable 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}"
|
||||
136
deploy/remote-deploy-tongweb.py
Normal file
136
deploy/remote-deploy-tongweb.py
Normal 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)
|
||||
Reference in New Issue
Block a user