From 5fb79a7c8d99c25b13c7c916f7b82dcbaf128da8 Mon Sep 17 00:00:00 2001 From: "xiuting.xu" Date: Fri, 17 Jul 2026 09:51:53 +0800 Subject: [PATCH] modify scripts --- scripts/01_start.sh | 86 ++++++++++++++--- scripts/04_cleanup.sh | 152 +++++++++++++++++++++++++++++ scripts/README.md | 218 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 444 insertions(+), 12 deletions(-) create mode 100644 scripts/04_cleanup.sh create mode 100644 scripts/README.md diff --git a/scripts/01_start.sh b/scripts/01_start.sh index 308db65..25a7976 100644 --- a/scripts/01_start.sh +++ b/scripts/01_start.sh @@ -4,23 +4,25 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" -COMMON_ENV_FILE="${ROOT_DIR}/environment" +COMMON_ENV_FILE="${ROOT_DIR}/environment.server" SERVER_ENV_FILE="${ROOT_DIR}/deploy/server/.env" CONSOLE_ENV_FILE="${ROOT_DIR}/deploy/console/.env" CONSOLE_COMPOSE_FILE="${ROOT_DIR}/deploy/console/docker-compose.yml" MODE="${RPKI_RTR_SERVER_MODE:-tcp}" COMPOSE_PROJECT="${RPKI_RTR_COMPOSE_PROJECT:-rpki-rtr}" CONSOLE_COMPOSE_PROJECT="${RPKI_CONSOLE_COMPOSE_PROJECT:-rpki-console}" +WAIT_SECS="${RPKI_START_WAIT_SECS:-20}" usage() { cat <<'EOF' Usage: scripts/01_start.sh [options] -Read root ./environment, update deploy/server/.env, then start the RTR server and console. +Read root ./environment.server, update deploy/server/.env, then start the RTR server and console. Options: - --env FILE Common env file. Default: ./environment + --env FILE Common env file. Default: ./environment.server --mode MODE Server mode: tcp|tls|ssh|base. Default: tcp + --wait SECS Wait timeout for container running checks. Default: 20 -h, --help Show this help. EOF } @@ -94,6 +96,63 @@ update_env_from_common() { printf '%s\n' "${updated_count}" } +server_compose() { + "${COMPOSE_BIN[@]}" --env-file "${SERVER_ENV_FILE}" -p "${COMPOSE_PROJECT}" -f "${SERVER_COMPOSE_FILE}" "$@" +} + +console_compose() { + "${COMPOSE_BIN[@]}" --env-file "${CONSOLE_ENV_FILE}" -p "${CONSOLE_COMPOSE_PROJECT}" -f "${CONSOLE_COMPOSE_FILE}" "$@" +} + +container_running() { + local compose_kind="$1" + local service="$2" + local cid state + + if [ "${compose_kind}" = "server" ]; then + cid="$(server_compose ps -q "${service}" 2>/dev/null || true)" + else + cid="$(console_compose ps -q "${service}" 2>/dev/null || true)" + fi + + [ -n "${cid}" ] || return 1 + state="$(docker inspect -f '{{.State.Running}}' "${cid}" 2>/dev/null || true)" + [ "${state}" = "true" ] +} + +show_service_debug() { + local compose_kind="$1" + local service="$2" + + log "${service} is not running, current compose status:" + if [ "${compose_kind}" = "server" ]; then + server_compose ps "${service}" >&2 || true + log "${service} recent logs:" + server_compose logs --tail=80 "${service}" >&2 || true + else + console_compose ps "${service}" >&2 || true + log "${service} recent logs:" + console_compose logs --tail=80 "${service}" >&2 || true + fi +} + +wait_for_running() { + local compose_kind="$1" + local service="$2" + local deadline=$((SECONDS + WAIT_SECS)) + + while [ "${SECONDS}" -lt "${deadline}" ]; do + if container_running "${compose_kind}" "${service}"; then + log "${service} is running" + return 0 + fi + sleep 1 + done + + show_service_debug "${compose_kind}" "${service}" + die "${service} failed to reach running state after ${WAIT_SECS}s" +} + while [ "$#" -gt 0 ]; do case "$1" in --env) @@ -106,6 +165,11 @@ while [ "$#" -gt 0 ]; do MODE="$2" shift 2 ;; + --wait) + [ "$#" -ge 2 ] || die "--wait requires a value" + WAIT_SECS="$2" + shift 2 + ;; -h|--help) usage exit 0 @@ -139,21 +203,19 @@ if [ -f "${COMMON_ENV_FILE}" ]; then log "updated ${server_updated_count} server env variable(s)" else stage "Reading Environment" - log "environment file not found, skip env update" + log "environment.server file not found, skip env update" fi stage "Starting RTR Server" log "starting docker compose service: rpki-rtr" -"${COMPOSE_BIN[@]}" --env-file "${SERVER_ENV_FILE}" -p "${COMPOSE_PROJECT}" -f "${SERVER_COMPOSE_FILE}" up -d --no-build rpki-rtr - -log "checking server compose status" -"${COMPOSE_BIN[@]}" --env-file "${SERVER_ENV_FILE}" -p "${COMPOSE_PROJECT}" -f "${SERVER_COMPOSE_FILE}" ps rpki-rtr +server_compose up -d --no-build rpki-rtr +log "waiting for rpki-rtr to be running" +wait_for_running server rpki-rtr stage "Starting Console" log "starting docker compose service: rpki-console-ui" -"${COMPOSE_BIN[@]}" --env-file "${CONSOLE_ENV_FILE}" -p "${CONSOLE_COMPOSE_PROJECT}" -f "${CONSOLE_COMPOSE_FILE}" up -d --no-build rpki-console-ui - -log "checking console compose status" -"${COMPOSE_BIN[@]}" --env-file "${CONSOLE_ENV_FILE}" -p "${CONSOLE_COMPOSE_PROJECT}" -f "${CONSOLE_COMPOSE_FILE}" ps rpki-console-ui +console_compose up -d --no-build rpki-console-ui +log "waiting for rpki-console-ui to be running" +wait_for_running console rpki-console-ui stage "Start Finished" diff --git a/scripts/04_cleanup.sh b/scripts/04_cleanup.sh new file mode 100644 index 0000000..536ff85 --- /dev/null +++ b/scripts/04_cleanup.sh @@ -0,0 +1,152 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +SERVER_DIR="${ROOT_DIR}/deploy/server" +SERVER_ENV_FILE="${SERVER_DIR}/.env" +SERVER_COMPOSE_FILE="${SERVER_DIR}/docker-compose.tcp.yml" +COMPOSE_PROJECT="${RPKI_RTR_COMPOSE_PROJECT:-rpki-rtr}" +FORCE=0 + +usage() { + cat <<'EOF' +Usage: scripts/04_cleanup.sh [options] + +Remove server generated directories: logs, reports, and RTR database. + +Options: + --force Clean even if the server container appears to be running. + -h, --help Show this help. +EOF +} + +log() { + printf '[04_cleanup] %s\n' "$*" >&2 +} + +stage() { + printf '\n====== %s ======\n' "$*" >&2 +} + +die() { + printf '[04_cleanup] ERROR: %s\n' "$*" >&2 + exit 1 +} + +env_value() { + local key="$1" + local default_value="$2" + local line + + line="$(grep -E "^[[:space:]]*${key}=" "${SERVER_ENV_FILE}" | tail -n 1 || true)" + if [ -n "${line}" ]; then + printf '%s\n' "${line#*=}" + else + printf '%s\n' "${default_value}" + fi +} + +resolve_host_path() { + local raw_path="$1" + + case "${raw_path}" in + /*|[A-Za-z]:/*|[A-Za-z]:\\*) + printf '%s\n' "${raw_path}" + ;; + *) + (cd "${SERVER_DIR}" && cd "${raw_path}" 2>/dev/null && pwd -P) || printf '%s/%s\n' "${SERVER_DIR}" "${raw_path}" + ;; + esac +} + +compose_available() { + if docker compose version >/dev/null 2>&1; then + COMPOSE_BIN=(docker compose) + return 0 + fi + + if command -v docker-compose >/dev/null 2>&1 && docker-compose version >/dev/null 2>&1; then + COMPOSE_BIN=(docker-compose) + return 0 + fi + + return 1 +} + +server_running() { + local cid state + + [ -f "${SERVER_COMPOSE_FILE}" ] || return 1 + compose_available || return 1 + + cid="$("${COMPOSE_BIN[@]}" --env-file "${SERVER_ENV_FILE}" -p "${COMPOSE_PROJECT}" -f "${SERVER_COMPOSE_FILE}" ps -q rpki-rtr 2>/dev/null || true)" + [ -n "${cid}" ] || return 1 + + state="$(docker inspect -f '{{.State.Running}}' "${cid}" 2>/dev/null || true)" + [ "${state}" = "true" ] +} + +clean_dir() { + local label="$1" + local path="$2" + local root_with_slash + + if [ ! -d "${path}" ]; then + log "${label}: ${path} not found, skip" + return 0 + fi + + root_with_slash="${ROOT_DIR}/" + case "${path}/" in + "${root_with_slash}"*) ;; + *) + log "ERROR: ${label} path is outside repo root, refuse to remove: ${path}" + return 1 + ;; + esac + + log "${label}: removing ${path}" + if ! rm -rf "${path}"; then + log "ERROR: failed to remove ${label}: ${path}" + return 1 + fi +} + +while [ "$#" -gt 0 ]; do + case "$1" in + --force) + FORCE=1 + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + die "unknown option: $1" + ;; + esac +done + +stage "Checking Server" +[ -f "${SERVER_ENV_FILE}" ] || die "server env file not found: ${SERVER_ENV_FILE}" +if [ "${FORCE}" -ne 1 ] && command -v docker >/dev/null 2>&1 && server_running; then + die "rpki-rtr is still running, run scripts/03_shutdown.sh first or use --force" +fi + +LOG_DIR="${ROOT_DIR}/logs" +REPORT_DIR="$(resolve_host_path "$(env_value RPKI_RTR_REPORT_HOST_DIR '../../report')")" +DB_DIR="$(resolve_host_path "$(env_value RPKI_RTR_DB_HOST_DIR '../../rtr-db')")" + +stage "Removing Server Files" +failed_count=0 +clean_dir "logs" "${LOG_DIR}" || failed_count=$((failed_count + 1)) +clean_dir "report" "${REPORT_DIR}" || failed_count=$((failed_count + 1)) +clean_dir "rtr-db" "${DB_DIR}" || failed_count=$((failed_count + 1)) + +if [ "${failed_count}" -gt 0 ]; then + die "${failed_count} cleanup item(s) failed" +fi + +stage "Cleanup Finished" diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..751d94e --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,218 @@ +# 脚本说明 + +`scripts/` 目录用于离线安装、启动、健康检查、关闭和清理。 + +所有脚本建议在仓库根目录执行: + +```bash +bash scripts/00_0_install.sh +``` + +## 目录 + +- [推荐流程](#推荐流程) +- [环境变量文件](#环境变量文件) +- [00 安装](#00-安装) +- [00 Pre-Check](#00-pre-check) +- [01 启动 Server 和 Console](#01-启动-server-和-console) +- [02 自检](#02-自检) +- [03 关闭 Server 和 Console](#03-关闭-server-和-console) +- [04 清理](#04-清理) +- [10 生成证书](#10-生成证书) +- [11 启动 Client](#11-启动-client) +- [12 关闭 Client](#12-关闭-client) +- [Windows 路径注意事项](#windows-路径注意事项) + +## 推荐流程 + +```bash +# 1. 加载镜像并执行 pre-check。 +bash scripts/00_0_install.sh + +# 2. 启动真实 server 和 console。 +bash scripts/01_start.sh --mode tcp + +# 3. 检查 server 和 console 是否正常。 +bash scripts/02_self_check.sh + +# 4. 关闭 server 和 console。 +bash scripts/03_shutdown.sh --mode tcp + +# 5. 清理 server 运行产生的文件。 +bash scripts/04_cleanup.sh +``` + +client 单独启动和关闭: + +```bash +bash scripts/11_start_client.sh --mode tcp +bash scripts/12_shutdown_client.sh --mode tcp +``` + +支持的模式: + +- server:`tcp`、`tls`、`ssh`、`base` +- client:`tcp`、`tls`、`ssh` + +## 环境变量文件 + +`01_start.sh` 会读取根目录下的 `environment.server`。如果文件存在,会将其中所有 `KEY=VALUE` 同步到 `deploy/server/.env`。 + +示例: + +```env +RPKI_RTR_CCR_HOST_DIR=/opt/rpki-rtr/data +RPKI_RTR_SLURM_HOST_DIR=/opt/rpki-rtr/data +RPKI_RTR_DB_HOST_DIR=/opt/rpki-rtr/rtr-db +RPKI_RTR_LOG_HOST_DIR=/opt/rpki-rtr/logs/server +RPKI_RTR_REPORT_HOST_DIR=/opt/rpki-rtr/report +``` + +`11_start_client.sh` 会读取根目录下的 `environment.client`。如果文件存在,会将其中所有 `KEY=VALUE` 同步到 `deploy/client/.env`。 + +如果 `environment.server` 或 `environment.client` 不存在,对应脚本会跳过更新,直接使用已有的 deploy `.env` 文件。 + +## 00 安装 + +`00_0_install.sh` 用于从 `images/` 目录加载离线 Docker 镜像,更新 deploy `.env` 中的镜像名,然后执行 pre-check。 + +默认镜像包查找规则: + +- server:`images/rpki-rtr-*.tar`,排除 `rpki-rtr-debug-client-*.tar` +- client:`images/rpki-rtr-debug-client-*.tar` +- console:`images/rpki-console-ui-*.tar` + +也可以显式指定镜像包: + +```bash +bash scripts/00_0_install.sh \ + --server-tar images/rpki-rtr-amd64-v1.2.tar \ + --client-tar images/rpki-rtr-debug-client-amd64-v1.2.tar \ + --console-tar images/rpki-console-ui-amd64-v1.0.tar +``` + +脚本会从 `docker load` 输出中解析真实镜像名,并写入: + +- `deploy/server/.env` 的 `RPKI_RTR_SERVER_IMAGE` +- `deploy/console/.env` 的 `RPKI_CONSOLE_UI_IMAGE` + +## 00 Pre-Check + +`00_1_pre_check.sh` 会在 `.precheck/` 下准备隔离测试数据,使用仓库里的 Docker Compose 文件启动 server 和 debug client,然后检查: + +- admin health 接口返回正常。 +- server 写出了 source report。 +- debug client 收到了 EndOfData 和 payload summary。 +- pre-check 日志中没有 fatal 错误模式。 + +相关辅助脚本: + +- `00_2_generate_ccr.sh`:生成固定的 CCR 测试文件。 +- `00_2_pre_check_prepare.sh`:创建 `.precheck/` 数据、SLURM 文件和 env 文件。 +- `00_3_pre_check_cleanup.sh`:停止 pre-check 容器并清理 `.precheck/`。 + +## 01 启动 Server 和 Console + +`01_start.sh` 用于启动真实的 RTR server 和 console。 + +```bash +bash scripts/01_start.sh --mode tcp +``` + +启动后脚本会检查容器是否进入 `running` 状态。如果容器启动后退出,脚本会打印 compose 状态和最近日志,然后报错退出,不会继续打印 `Start Finished`。 + +常用参数: + +```bash +bash scripts/01_start.sh --mode tls +bash scripts/01_start.sh --mode ssh +bash scripts/01_start.sh --wait 60 +bash scripts/01_start.sh --env ./environment.server +``` + +注意:console 不读取 `environment.server`,只使用 `deploy/console/.env`。 + +## 02 自检 + +`02_self_check.sh` 用于检查 `01_start.sh` 启动的 server 和 console 是否正常。 + +```bash +bash scripts/02_self_check.sh +``` + +检查内容包括: + +- server 容器是否 running。 +- console 容器是否 running。 +- RTR TCP 端口是否可连接。 +- admin health 接口是否健康。 +- console 端口和 HTTP 根路径是否可访问。 + +如果启动较慢,可以增加等待时间: + +```bash +bash scripts/02_self_check.sh --wait 120 +``` + +## 03 关闭 Server 和 Console + +`03_shutdown.sh` 用于关闭 `01_start.sh` 启动的服务。 + +```bash +bash scripts/03_shutdown.sh --mode tcp +``` + +脚本会先关闭 console,再关闭 RTR server。 + +## 04 清理 + +`04_cleanup.sh` 用于删除 server 运行产生的目录: + +- `logs/` +- `report/` +- `rtr-db/` + +推荐先关闭服务,再清理: + +```bash +bash scripts/03_shutdown.sh +bash scripts/04_cleanup.sh +``` + +清理前脚本会检查 `rpki-rtr` 是否仍在运行。如果仍在运行,会拒绝清理。只有明确需要强制清理时才使用: + +```bash +bash scripts/04_cleanup.sh --force +``` + +清理脚本会拒绝删除仓库根目录之外的路径。如果某一项清理失败,会继续清理后续项,最后返回失败。 + +## 10 生成证书 + +`10_generate_certs.sh` 用于生成 TLS/SSH 模式需要的本地证书材料(测试用)。 + +```bash +bash scripts/10_generate_certs.sh +``` + +## 11 启动 Client + +`11_start_client.sh` 用于启动 RTR debug client。 + +```bash +bash scripts/11_start_client.sh --mode tcp +bash scripts/11_start_client.sh --mode tls +bash scripts/11_start_client.sh --mode ssh +``` + +如果 `environment.client` 存在,脚本会将其中所有 `KEY=VALUE` 同步到 `deploy/client/.env`;如果不存在,则直接使用已有的 `deploy/client/.env`。 + +## 12 关闭 Client + +`12_shutdown_client.sh` 用于关闭 `11_start_client.sh` 启动的 client。 + +```bash +bash scripts/12_shutdown_client.sh --mode tcp +``` + +关闭时建议使用和启动时相同的 mode。