75b85ee5a9
direct live 支持独立 redirect base URL 预期 release readiness 和切换证据链透传 redirect base URL 直连启用脚本透传高端口 rehearsal 参数 补充 direct live guard、运维门禁和文档示例
923 lines
34 KiB
Bash
923 lines
34 KiB
Bash
#!/usr/bin/env bash
|
||
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd)"
|
||
SERVICE_NAME="${GENARRATIVE_PINGORA_GATEWAY_SERVICE:-genarrative-pingora-gateway.service}"
|
||
DEFAULT_SERVICE_UNIT_PATH="${REPO_ROOT}/deploy/systemd/genarrative-pingora-gateway.service"
|
||
SERVICE_UNIT_PATH="${GENARRATIVE_PINGORA_DIRECT_SERVICE_UNIT_PATH:-${DEFAULT_SERVICE_UNIT_PATH}}"
|
||
DEFAULT_TEMPLATE_PATH="${REPO_ROOT}/deploy/systemd/genarrative-pingora-gateway-direct-entry.conf"
|
||
TEMPLATE_PATH="${GENARRATIVE_PINGORA_DIRECT_TEMPLATE_PATH:-${DEFAULT_TEMPLATE_PATH}}"
|
||
DROPIN_PATH="${GENARRATIVE_PINGORA_DIRECT_DROPIN_PATH:-/etc/systemd/system/genarrative-pingora-gateway.service.d/direct-entry.conf}"
|
||
PREFLIGHT_SCRIPT="${GENARRATIVE_PINGORA_DIRECT_PREFLIGHT_SCRIPT:-${REPO_ROOT}/scripts/check-pingora-direct-preflight.mjs}"
|
||
PREFLIGHT_ENV_FILE="${GENARRATIVE_PINGORA_DIRECT_PREFLIGHT_ENV_FILE:-}"
|
||
CURRENT_RELEASE_AUDIT_SCRIPT="${GENARRATIVE_PINGORA_DIRECT_CURRENT_RELEASE_AUDIT_SCRIPT:-${REPO_ROOT}/scripts/ops/pingora-current-release-audit.mjs}"
|
||
CURRENT_RELEASE_ROOT="${GENARRATIVE_PINGORA_DIRECT_CURRENT_RELEASE_ROOT:-${REPO_ROOT}}"
|
||
CURRENT_RELEASE_AUDIT_TIMEOUT_MS="${GENARRATIVE_PINGORA_DIRECT_CURRENT_RELEASE_AUDIT_TIMEOUT_MS:-}"
|
||
PREFLIGHT_SYSTEMD="false"
|
||
PREFLIGHT_CHECK_CERT_READABLE="false"
|
||
PREFLIGHT_CHECK_SERVICE_ENV_FILE="false"
|
||
PREFLIGHT_CHECK_SERVICE_USER_CERT_READABLE="false"
|
||
PREFLIGHT_CHECK_SERVICE_BINARY_EXECUTABLE="false"
|
||
PREFLIGHT_CHECK_PORTS_FREE="false"
|
||
DIRECT_LIVE_SCRIPT="${GENARRATIVE_PINGORA_DIRECT_LIVE_SCRIPT:-${REPO_ROOT}/scripts/check-pingora-direct-live.mjs}"
|
||
DIRECT_HTTPS_BASE_URL="${GENARRATIVE_PINGORA_DIRECT_HTTPS_BASE_URL:-}"
|
||
DIRECT_HTTP_BASE_URL="${GENARRATIVE_PINGORA_DIRECT_HTTP_BASE_URL:-}"
|
||
DIRECT_HOST="${GENARRATIVE_PINGORA_DIRECT_HOST:-}"
|
||
DIRECT_REDIRECT_HOST="${GENARRATIVE_PINGORA_DIRECT_REDIRECT_HOST:-}"
|
||
DIRECT_REDIRECT_BASE_URL="${GENARRATIVE_PINGORA_DIRECT_REDIRECT_BASE_URL:-}"
|
||
DIRECT_PROBE_TOKEN="${GENARRATIVE_PINGORA_DIRECT_PROBE_TOKEN:-}"
|
||
DIRECT_PINGORA_ACCESS_LOG="${GENARRATIVE_PINGORA_DIRECT_PINGORA_ACCESS_LOG:-}"
|
||
DIRECT_ACCESS_LOG_SINCE_LINES="${GENARRATIVE_PINGORA_DIRECT_ACCESS_LOG_SINCE_LINES:-}"
|
||
DIRECT_SPACETIME_DATABASE="${GENARRATIVE_PINGORA_DIRECT_SPACETIME_DATABASE:-}"
|
||
DIRECT_TIMEOUT_MS="${GENARRATIVE_PINGORA_DIRECT_TIMEOUT_MS:-}"
|
||
APPLY="false"
|
||
STATUS_AFTER="true"
|
||
VERIFY_SYSTEMD_AFTER="true"
|
||
|
||
usage() {
|
||
cat <<'EOF'
|
||
用法:
|
||
scripts/deploy/pingora-direct-enable.sh [--apply] [--preflight-env-file <path>] [--preflight-systemd] [--preflight-check-cert-readable] [--preflight-check-service-env-file] [--preflight-check-service-user-cert-readable] [--preflight-check-service-binary-executable] [--preflight-check-ports-free]
|
||
[--direct-https-base-url <url>] [--direct-http-base-url <url>] [--direct-host <host>] [--direct-redirect-host <host>] [--direct-redirect-base-url <url>]
|
||
[--direct-spacetime-database <name>] [--direct-probe-token <token>] [--direct-pingora-access-log <path>] [--direct-access-log-since-lines <count>] [--direct-timeout-ms <ms>] [--direct-live-script <path>] [--no-postcheck]
|
||
[--current-release-audit-script <path>] [--current-release-root <path>] [--current-release-audit-timeout-ms <ms>]
|
||
[--service <name>] [--service-unit-path <path>] [--template-path <path>] [--dropin-path <path>]
|
||
|
||
说明:
|
||
启用 Pingora 直连低端口入口:把已准备好的 direct-entry systemd drop-in 模板安装到
|
||
genarrative-pingora-gateway.service.d/direct-entry.conf,执行 daemon-reload,
|
||
重启 genarrative-pingora-gateway.service,让服务具备绑定 80/443 的最小 capability。
|
||
|
||
默认是 dry-run,只打印将执行的命令;必须显式传 --apply 才会修改系统状态。
|
||
该脚本不写入 TLS env、不复制证书、不停止 Nginx;--apply 会先执行 current release 自包含自审,
|
||
确认发布包已携带 Pingora 网关且 systemd ExecStart 指向随包二进制;--apply 时必须提供 --preflight-env-file、
|
||
--preflight-check-cert-readable、--preflight-check-service-env-file、--preflight-check-service-user-cert-readable、--preflight-check-service-binary-executable、--preflight-check-ports-free 和 direct live smoke 参数,
|
||
先通过 direct preflight,安装并重启 Pingora,再通过 direct live smoke 后才视为启用成功。
|
||
EOF
|
||
}
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
-h|--help)
|
||
usage
|
||
exit 0
|
||
;;
|
||
--apply)
|
||
APPLY="true"
|
||
shift
|
||
;;
|
||
--no-status)
|
||
STATUS_AFTER="false"
|
||
shift
|
||
;;
|
||
--no-postcheck)
|
||
VERIFY_SYSTEMD_AFTER="false"
|
||
shift
|
||
;;
|
||
--service)
|
||
SERVICE_NAME="${2:-}"
|
||
if [[ -z "${SERVICE_NAME}" ]]; then
|
||
echo "[pingora-direct-enable] --service 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--service-unit-path)
|
||
SERVICE_UNIT_PATH="${2:-}"
|
||
if [[ -z "${SERVICE_UNIT_PATH}" ]]; then
|
||
echo "[pingora-direct-enable] --service-unit-path 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--template-path)
|
||
TEMPLATE_PATH="${2:-}"
|
||
if [[ -z "${TEMPLATE_PATH}" ]]; then
|
||
echo "[pingora-direct-enable] --template-path 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--dropin-path)
|
||
DROPIN_PATH="${2:-}"
|
||
if [[ -z "${DROPIN_PATH}" ]]; then
|
||
echo "[pingora-direct-enable] --dropin-path 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--preflight-script)
|
||
PREFLIGHT_SCRIPT="${2:-}"
|
||
if [[ -z "${PREFLIGHT_SCRIPT}" ]]; then
|
||
echo "[pingora-direct-enable] --preflight-script 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--preflight-env-file)
|
||
PREFLIGHT_ENV_FILE="${2:-}"
|
||
if [[ -z "${PREFLIGHT_ENV_FILE}" ]]; then
|
||
echo "[pingora-direct-enable] --preflight-env-file 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--current-release-audit-script)
|
||
CURRENT_RELEASE_AUDIT_SCRIPT="${2:-}"
|
||
if [[ -z "${CURRENT_RELEASE_AUDIT_SCRIPT}" ]]; then
|
||
echo "[pingora-direct-enable] --current-release-audit-script 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--current-release-root)
|
||
CURRENT_RELEASE_ROOT="${2:-}"
|
||
if [[ -z "${CURRENT_RELEASE_ROOT}" ]]; then
|
||
echo "[pingora-direct-enable] --current-release-root 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--current-release-audit-timeout-ms)
|
||
CURRENT_RELEASE_AUDIT_TIMEOUT_MS="${2:-}"
|
||
if [[ -z "${CURRENT_RELEASE_AUDIT_TIMEOUT_MS}" ]]; then
|
||
echo "[pingora-direct-enable] --current-release-audit-timeout-ms 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--preflight-systemd)
|
||
PREFLIGHT_SYSTEMD="true"
|
||
shift
|
||
;;
|
||
--preflight-check-cert-readable)
|
||
PREFLIGHT_CHECK_CERT_READABLE="true"
|
||
shift
|
||
;;
|
||
--preflight-check-service-env-file)
|
||
PREFLIGHT_CHECK_SERVICE_ENV_FILE="true"
|
||
shift
|
||
;;
|
||
--preflight-check-service-user-cert-readable)
|
||
PREFLIGHT_CHECK_SERVICE_USER_CERT_READABLE="true"
|
||
shift
|
||
;;
|
||
--preflight-check-service-binary-executable)
|
||
PREFLIGHT_CHECK_SERVICE_BINARY_EXECUTABLE="true"
|
||
shift
|
||
;;
|
||
--preflight-check-ports-free)
|
||
PREFLIGHT_CHECK_PORTS_FREE="true"
|
||
shift
|
||
;;
|
||
--direct-live-script)
|
||
DIRECT_LIVE_SCRIPT="${2:-}"
|
||
if [[ -z "${DIRECT_LIVE_SCRIPT}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-live-script 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-https-base-url)
|
||
DIRECT_HTTPS_BASE_URL="${2:-}"
|
||
if [[ -z "${DIRECT_HTTPS_BASE_URL}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-https-base-url 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-http-base-url)
|
||
DIRECT_HTTP_BASE_URL="${2:-}"
|
||
if [[ -z "${DIRECT_HTTP_BASE_URL}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-http-base-url 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-host)
|
||
DIRECT_HOST="${2:-}"
|
||
if [[ -z "${DIRECT_HOST}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-host 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-redirect-host)
|
||
DIRECT_REDIRECT_HOST="${2:-}"
|
||
if [[ -z "${DIRECT_REDIRECT_HOST}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-redirect-host 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-redirect-base-url)
|
||
DIRECT_REDIRECT_BASE_URL="${2:-}"
|
||
if [[ -z "${DIRECT_REDIRECT_BASE_URL}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-redirect-base-url 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-probe-token)
|
||
DIRECT_PROBE_TOKEN="${2:-}"
|
||
if [[ -z "${DIRECT_PROBE_TOKEN}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-probe-token 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-pingora-access-log)
|
||
DIRECT_PINGORA_ACCESS_LOG="${2:-}"
|
||
if [[ -z "${DIRECT_PINGORA_ACCESS_LOG}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-pingora-access-log 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-access-log-since-lines)
|
||
DIRECT_ACCESS_LOG_SINCE_LINES="${2:-}"
|
||
if [[ -z "${DIRECT_ACCESS_LOG_SINCE_LINES}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-access-log-since-lines 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-spacetime-database)
|
||
DIRECT_SPACETIME_DATABASE="${2:-}"
|
||
if [[ -z "${DIRECT_SPACETIME_DATABASE}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-spacetime-database 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
--direct-timeout-ms)
|
||
DIRECT_TIMEOUT_MS="${2:-}"
|
||
if [[ -z "${DIRECT_TIMEOUT_MS}" ]]; then
|
||
echo "[pingora-direct-enable] --direct-timeout-ms 缺少参数" >&2
|
||
exit 1
|
||
fi
|
||
shift 2
|
||
;;
|
||
*)
|
||
echo "[pingora-direct-enable] 未知参数: $1" >&2
|
||
usage >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
reject_control_characters() {
|
||
local label="$1"
|
||
local value="$2"
|
||
if [[ "${value}" == *$'\n'* || "${value}" == *$'\r'* ]]; then
|
||
echo "[pingora-direct-enable] ${label} 不能包含换行或 NUL 字符。" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
is_filesystem_root_path() {
|
||
local value="$1"
|
||
local without_slashes="${value//\//}"
|
||
[[ -n "${value}" && -z "${without_slashes}" ]]
|
||
}
|
||
|
||
reject_filesystem_root_path() {
|
||
local label="$1"
|
||
local value="$2"
|
||
if is_filesystem_root_path "${value}"; then
|
||
echo "[pingora-direct-enable] ${label} 不能是文件系统根目录。" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
reject_control_characters "--service" "${SERVICE_NAME}"
|
||
reject_control_characters "--service-unit-path" "${SERVICE_UNIT_PATH}"
|
||
reject_control_characters "--template-path" "${TEMPLATE_PATH}"
|
||
reject_control_characters "--dropin-path" "${DROPIN_PATH}"
|
||
reject_control_characters "--preflight-script" "${PREFLIGHT_SCRIPT}"
|
||
reject_control_characters "--preflight-env-file" "${PREFLIGHT_ENV_FILE}"
|
||
reject_control_characters "--current-release-audit-script" "${CURRENT_RELEASE_AUDIT_SCRIPT}"
|
||
reject_control_characters "--current-release-root" "${CURRENT_RELEASE_ROOT}"
|
||
reject_control_characters "--current-release-audit-timeout-ms" "${CURRENT_RELEASE_AUDIT_TIMEOUT_MS}"
|
||
reject_control_characters "--direct-live-script" "${DIRECT_LIVE_SCRIPT}"
|
||
reject_control_characters "--direct-https-base-url" "${DIRECT_HTTPS_BASE_URL}"
|
||
reject_control_characters "--direct-http-base-url" "${DIRECT_HTTP_BASE_URL}"
|
||
reject_control_characters "--direct-host" "${DIRECT_HOST}"
|
||
reject_control_characters "--direct-redirect-host" "${DIRECT_REDIRECT_HOST}"
|
||
reject_control_characters "--direct-redirect-base-url" "${DIRECT_REDIRECT_BASE_URL}"
|
||
reject_control_characters "--direct-probe-token" "${DIRECT_PROBE_TOKEN}"
|
||
reject_control_characters "--direct-pingora-access-log" "${DIRECT_PINGORA_ACCESS_LOG}"
|
||
reject_control_characters "--direct-access-log-since-lines" "${DIRECT_ACCESS_LOG_SINCE_LINES}"
|
||
reject_control_characters "--direct-spacetime-database" "${DIRECT_SPACETIME_DATABASE}"
|
||
reject_control_characters "--direct-timeout-ms" "${DIRECT_TIMEOUT_MS}"
|
||
|
||
reject_filesystem_root_path "--service-unit-path" "${SERVICE_UNIT_PATH}"
|
||
reject_filesystem_root_path "--template-path" "${TEMPLATE_PATH}"
|
||
reject_filesystem_root_path "--dropin-path" "${DROPIN_PATH}"
|
||
reject_filesystem_root_path "--preflight-env-file" "${PREFLIGHT_ENV_FILE}"
|
||
reject_filesystem_root_path "--preflight-script" "${PREFLIGHT_SCRIPT}"
|
||
reject_filesystem_root_path "--current-release-audit-script" "${CURRENT_RELEASE_AUDIT_SCRIPT}"
|
||
reject_filesystem_root_path "--current-release-root" "${CURRENT_RELEASE_ROOT}"
|
||
reject_filesystem_root_path "--direct-live-script" "${DIRECT_LIVE_SCRIPT}"
|
||
reject_filesystem_root_path "--direct-pingora-access-log" "${DIRECT_PINGORA_ACCESS_LOG}"
|
||
|
||
if [[ "${TEMPLATE_PATH}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --template-path 必须是绝对路径: ${TEMPLATE_PATH}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${SERVICE_UNIT_PATH}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --service-unit-path 必须是绝对路径: ${SERVICE_UNIT_PATH}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${DROPIN_PATH}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --dropin-path 必须是绝对路径: ${DROPIN_PATH}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ -n "${PREFLIGHT_ENV_FILE}" && "${PREFLIGHT_ENV_FILE}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --preflight-env-file 必须是绝对路径: ${PREFLIGHT_ENV_FILE}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${PREFLIGHT_SCRIPT}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --preflight-script 必须是绝对路径: ${PREFLIGHT_SCRIPT}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${CURRENT_RELEASE_AUDIT_SCRIPT}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --current-release-audit-script 必须是绝对路径: ${CURRENT_RELEASE_AUDIT_SCRIPT}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${CURRENT_RELEASE_ROOT}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --current-release-root 必须是绝对路径: ${CURRENT_RELEASE_ROOT}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${DIRECT_LIVE_SCRIPT}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --direct-live-script 必须是绝对路径: ${DIRECT_LIVE_SCRIPT}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && -z "${PREFLIGHT_ENV_FILE}" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --preflight-env-file,避免跳过直连 env / 证书预检。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && "${PREFLIGHT_CHECK_CERT_READABLE}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --preflight-check-cert-readable,避免跳过 TLS 证书和私钥可读预检。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && "${PREFLIGHT_CHECK_SERVICE_ENV_FILE}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --preflight-check-service-env-file,避免检查的 env 文件和 systemd service 实际读取的 EnvironmentFile 不一致。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && "${PREFLIGHT_CHECK_SERVICE_USER_CERT_READABLE}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --preflight-check-service-user-cert-readable,避免跳过 systemd 服务用户读取 TLS 证书和私钥预检。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && "${PREFLIGHT_CHECK_SERVICE_BINARY_EXECUTABLE}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --preflight-check-service-binary-executable,避免 current release 缺少可执行 pingora-gateway 时才在重启阶段失败。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && "${PREFLIGHT_CHECK_PORTS_FREE}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --preflight-check-ports-free,避免 Nginx 或其它进程仍占用 80/443。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && -z "${DIRECT_HTTPS_BASE_URL}" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --direct-https-base-url,启用后验证 Pingora HTTPS 直连入口。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && -z "${DIRECT_HTTP_BASE_URL}" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --direct-http-base-url,启用后验证 HTTP redirect / ACME 入口。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && -z "${DIRECT_HOST}" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --direct-host,启用后用正式域名 Host/SNI 验证直连入口。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && -z "${DIRECT_REDIRECT_HOST}" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --direct-redirect-host,启用后验证 HTTP redirect Location host。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && -z "${DIRECT_PINGORA_ACCESS_LOG}" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --direct-pingora-access-log,启用后验证直连请求已写入 Pingora access log。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ -n "${DIRECT_PINGORA_ACCESS_LOG}" && "${DIRECT_PINGORA_ACCESS_LOG}" != /* ]]; then
|
||
echo "[pingora-direct-enable] --direct-pingora-access-log 必须是绝对路径: ${DIRECT_PINGORA_ACCESS_LOG}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && -z "${DIRECT_SPACETIME_DATABASE}" ]]; then
|
||
echo "[pingora-direct-enable] --apply 必须同时提供 --direct-spacetime-database,启用后验证目标库 WSS subscribe。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && ! -f "${TEMPLATE_PATH}" ]]; then
|
||
echo "[pingora-direct-enable] direct-entry 模板不存在: ${TEMPLATE_PATH}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && ! -f "${SERVICE_UNIT_PATH}" ]]; then
|
||
echo "[pingora-direct-enable] 主 service 模板不存在: ${SERVICE_UNIT_PATH}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && ! -f "${CURRENT_RELEASE_AUDIT_SCRIPT}" ]]; then
|
||
echo "[pingora-direct-enable] current release 自审脚本不存在: ${CURRENT_RELEASE_AUDIT_SCRIPT}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && ! -f "${PREFLIGHT_SCRIPT}" ]]; then
|
||
echo "[pingora-direct-enable] direct preflight 脚本不存在: ${PREFLIGHT_SCRIPT}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" && ! -f "${DIRECT_LIVE_SCRIPT}" ]]; then
|
||
echo "[pingora-direct-enable] direct live smoke 脚本不存在: ${DIRECT_LIVE_SCRIPT}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" == "true" ]]; then
|
||
DROPIN_DIR="$(dirname "${DROPIN_PATH}")"
|
||
if [[ -L "${DROPIN_DIR}" ]]; then
|
||
echo "[pingora-direct-enable] drop-in 目录不能是符号链接: ${DROPIN_DIR}" >&2
|
||
exit 1
|
||
fi
|
||
if [[ -e "${DROPIN_DIR}" && ! -d "${DROPIN_DIR}" ]]; then
|
||
echo "[pingora-direct-enable] drop-in 父路径必须是目录: ${DROPIN_DIR}" >&2
|
||
exit 1
|
||
fi
|
||
if [[ -L "${DROPIN_PATH}" ]]; then
|
||
echo "[pingora-direct-enable] drop-in 目标不能是符号链接: ${DROPIN_PATH}" >&2
|
||
exit 1
|
||
fi
|
||
if [[ -e "${DROPIN_PATH}" && ! -f "${DROPIN_PATH}" ]]; then
|
||
echo "[pingora-direct-enable] drop-in 目标已存在但不是普通文件: ${DROPIN_PATH}" >&2
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
run_cmd() {
|
||
echo "+ $*"
|
||
if [[ "${APPLY}" == "true" ]]; then
|
||
"$@"
|
||
fi
|
||
}
|
||
|
||
print_redacted_command() {
|
||
local previous="" output=()
|
||
for arg in "$@"; do
|
||
if [[ "${previous}" == "--probe-token" || "${previous}" == "--direct-probe-token" ]]; then
|
||
output+=("<redacted>")
|
||
else
|
||
output+=("${arg}")
|
||
fi
|
||
previous="${arg}"
|
||
done
|
||
echo "+ ${output[*]}"
|
||
}
|
||
|
||
run_systemctl() {
|
||
if [[ "${APPLY}" != "true" ]]; then
|
||
run_cmd systemctl "$@"
|
||
return
|
||
fi
|
||
if command -v systemctl >/dev/null 2>&1; then
|
||
run_cmd systemctl "$@"
|
||
else
|
||
echo "[pingora-direct-enable] 未找到 systemctl,无法执行: systemctl $*" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
run_preflight() {
|
||
if [[ -z "${PREFLIGHT_ENV_FILE}" ]]; then
|
||
echo "[pingora-direct-enable] 未提供 --preflight-env-file,仅执行脚本 dry-run;--apply 会强制要求预检。"
|
||
return
|
||
fi
|
||
|
||
preflight_args=(
|
||
"${PREFLIGHT_SCRIPT}"
|
||
--env-file "${PREFLIGHT_ENV_FILE}"
|
||
--require-live-env
|
||
)
|
||
if [[ "${PREFLIGHT_SYSTEMD}" == "true" ]]; then
|
||
preflight_args+=(--systemd-cat)
|
||
fi
|
||
if [[ "${PREFLIGHT_CHECK_CERT_READABLE}" == "true" ]]; then
|
||
preflight_args+=(--check-cert-readable)
|
||
fi
|
||
if [[ "${PREFLIGHT_CHECK_SERVICE_ENV_FILE}" == "true" ]]; then
|
||
preflight_args+=(--check-service-env-file)
|
||
fi
|
||
if [[ "${PREFLIGHT_CHECK_SERVICE_USER_CERT_READABLE}" == "true" ]]; then
|
||
preflight_args+=(--check-service-user-cert-readable)
|
||
fi
|
||
if [[ "${PREFLIGHT_CHECK_SERVICE_BINARY_EXECUTABLE}" == "true" ]]; then
|
||
preflight_args+=(--check-service-binary-executable)
|
||
fi
|
||
if [[ "${PREFLIGHT_CHECK_PORTS_FREE}" == "true" ]]; then
|
||
preflight_args+=(--check-ports-free)
|
||
fi
|
||
|
||
echo "+ node -- ${preflight_args[*]}"
|
||
node -- "${preflight_args[@]}"
|
||
}
|
||
|
||
run_current_release_audit() {
|
||
audit_args=(
|
||
"${CURRENT_RELEASE_AUDIT_SCRIPT}"
|
||
--release-root "${CURRENT_RELEASE_ROOT}"
|
||
--require-pingora-gateway
|
||
--systemd-show
|
||
--systemd-service "${SERVICE_NAME}"
|
||
)
|
||
if [[ -n "${CURRENT_RELEASE_AUDIT_TIMEOUT_MS}" ]]; then
|
||
audit_args+=(--timeout-ms "${CURRENT_RELEASE_AUDIT_TIMEOUT_MS}")
|
||
fi
|
||
|
||
echo "+ node -- ${audit_args[*]}"
|
||
if [[ "${APPLY}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] dry-run:--apply 前会先执行 current release 自包含自审。"
|
||
return
|
||
fi
|
||
|
||
node -- "${audit_args[@]}"
|
||
}
|
||
|
||
systemd_env_file_matches() {
|
||
local expected="$1"
|
||
local line value word normalized
|
||
while IFS= read -r line; do
|
||
line="${line#"${line%%[![:space:]]*}"}"
|
||
line="${line%"${line##*[![:space:]]}"}"
|
||
[[ "${line}" == EnvironmentFile=* ]] || continue
|
||
value="${line#EnvironmentFile=}"
|
||
[[ -n "${value}" ]] || continue
|
||
for word in ${value}; do
|
||
normalized="${word%\"}"
|
||
normalized="${normalized#\"}"
|
||
normalized="${normalized%\'}"
|
||
normalized="${normalized#\'}"
|
||
normalized="${normalized#-}"
|
||
if [[ "${normalized}" == "${expected}" ]]; then
|
||
return 0
|
||
fi
|
||
done
|
||
done <<<"${unit_content}"
|
||
return 1
|
||
}
|
||
|
||
read_expected_exec_start() {
|
||
local line value
|
||
if [[ ! -f "${SERVICE_UNIT_PATH}" ]]; then
|
||
return 1
|
||
fi
|
||
while IFS= read -r line; do
|
||
line="${line#"${line%%[![:space:]]*}"}"
|
||
line="${line%"${line##*[![:space:]]}"}"
|
||
[[ "${line}" == ExecStart=* ]] || continue
|
||
value="${line#ExecStart=}"
|
||
[[ -n "${value}" ]] || continue
|
||
printf '%s\n' "${value}"
|
||
return 0
|
||
done <"${SERVICE_UNIT_PATH}"
|
||
return 1
|
||
}
|
||
|
||
first_exec_word() {
|
||
local value="$1"
|
||
value="${value#"${value%%[![:space:]]*}"}"
|
||
value="${value%"${value##*[![:space:]]}"}"
|
||
if [[ "${value}" == \"* ]]; then
|
||
value="${value#\"}"
|
||
printf '%s\n' "${value%%\"*}"
|
||
return
|
||
fi
|
||
printf '%s\n' "${value%%[[:space:]]*}"
|
||
}
|
||
|
||
systemd_show_exec_start_matches() {
|
||
local expected_exec="$1"
|
||
local expected_binary actual_show actual_binary
|
||
expected_binary="$(first_exec_word "${expected_exec}")"
|
||
[[ -n "${expected_binary}" ]] || return 1
|
||
actual_show="$(systemctl show "${SERVICE_NAME}" --property=ExecStart --value --no-pager)"
|
||
actual_binary="${actual_show}"
|
||
if [[ "${actual_show}" == *"path="* ]]; then
|
||
actual_binary="${actual_show#*path=}"
|
||
actual_binary="${actual_binary%% ;*}"
|
||
elif [[ "${actual_show}" == ExecStart=* ]]; then
|
||
actual_binary="${actual_show#ExecStart=}"
|
||
actual_binary="$(first_exec_word "${actual_binary}")"
|
||
else
|
||
actual_binary="$(first_exec_word "${actual_binary}")"
|
||
fi
|
||
[[ "${actual_binary}" == "${expected_binary}" ]]
|
||
}
|
||
|
||
verify_systemd_exec_start() {
|
||
if [[ "${VERIFY_SYSTEMD_AFTER}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] 已跳过 Pingora ExecStart 指向核验。"
|
||
return
|
||
fi
|
||
|
||
expected_exec_start="$(read_expected_exec_start || true)"
|
||
if [[ -z "${expected_exec_start}" ]]; then
|
||
echo "[pingora-direct-enable] 无法从主 service 模板读取 ExecStart: ${SERVICE_UNIT_PATH}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${APPLY}" != "true" ]]; then
|
||
echo "+ systemctl show ${SERVICE_NAME} --property=ExecStart --value --no-pager"
|
||
echo "[pingora-direct-enable] dry-run:--apply 后会核验 systemd ExecStart 指向主 service 模板中的 ${expected_exec_start}。"
|
||
return
|
||
fi
|
||
|
||
if ! command -v systemctl >/dev/null 2>&1; then
|
||
echo "[pingora-direct-enable] 未找到 systemctl,无法核验 Pingora ExecStart。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "+ systemctl show ${SERVICE_NAME} --property=ExecStart --value --no-pager"
|
||
if ! systemd_show_exec_start_matches "${expected_exec_start}"; then
|
||
echo "[pingora-direct-enable] systemctl show ExecStart 未指向主 service 模板中的 ${expected_exec_start},请先修正 ${SERVICE_NAME} 指向 current release 网关二进制。" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
verify_systemd_dropin() {
|
||
if [[ "${VERIFY_SYSTEMD_AFTER}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] 已跳过 systemd drop-in 生效核验。"
|
||
return
|
||
fi
|
||
|
||
if [[ "${APPLY}" != "true" ]]; then
|
||
echo "+ systemctl cat ${SERVICE_NAME}"
|
||
echo "[pingora-direct-enable] dry-run:--apply 后会校验 systemd 最终配置包含 CAP_NET_BIND_SERVICE。"
|
||
return
|
||
fi
|
||
|
||
if ! command -v systemctl >/dev/null 2>&1; then
|
||
echo "[pingora-direct-enable] 未找到 systemctl,无法核验 drop-in 是否生效。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "+ systemctl cat ${SERVICE_NAME}"
|
||
unit_content="$(systemctl cat "${SERVICE_NAME}")"
|
||
if [[ "${unit_content}" != *"AmbientCapabilities=CAP_NET_BIND_SERVICE"* ]]; then
|
||
echo "[pingora-direct-enable] systemctl cat 未显示 AmbientCapabilities=CAP_NET_BIND_SERVICE,direct-entry drop-in 未生效。" >&2
|
||
exit 1
|
||
fi
|
||
if [[ "${unit_content}" != *"CapabilityBoundingSet=CAP_NET_BIND_SERVICE"* ]]; then
|
||
echo "[pingora-direct-enable] systemctl cat 未显示 CapabilityBoundingSet=CAP_NET_BIND_SERVICE,direct-entry drop-in 未生效。" >&2
|
||
exit 1
|
||
fi
|
||
if [[ "${PREFLIGHT_CHECK_SERVICE_ENV_FILE}" == "true" && -n "${PREFLIGHT_ENV_FILE}" ]]; then
|
||
if ! systemd_env_file_matches "${PREFLIGHT_ENV_FILE}"; then
|
||
echo "[pingora-direct-enable] systemctl cat 未显示 EnvironmentFile=${PREFLIGHT_ENV_FILE},service 实际读取的 env 与 preflight env 不一致。" >&2
|
||
exit 1
|
||
fi
|
||
fi
|
||
}
|
||
|
||
verify_service_active_after_restart() {
|
||
if [[ "${VERIFY_SYSTEMD_AFTER}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] 已跳过 Pingora 重启后状态核验。"
|
||
return
|
||
fi
|
||
|
||
if [[ "${APPLY}" != "true" ]]; then
|
||
echo "+ systemctl is-active ${SERVICE_NAME}"
|
||
echo "[pingora-direct-enable] dry-run:--apply 后会校验 Pingora service 为 active。"
|
||
return
|
||
fi
|
||
|
||
if ! command -v systemctl >/dev/null 2>&1; then
|
||
echo "[pingora-direct-enable] 未找到 systemctl,无法核验 Pingora 重启后状态。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "+ systemctl is-active ${SERVICE_NAME}"
|
||
service_state="$(systemctl is-active "${SERVICE_NAME}")"
|
||
if [[ "${service_state}" != "active" ]]; then
|
||
echo "[pingora-direct-enable] Pingora 重启后状态不是 active: ${service_state}" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
run_direct_live_smoke_after_enable() {
|
||
if [[ -z "${DIRECT_HTTPS_BASE_URL}" ]]; then
|
||
echo "+ node ${DIRECT_LIVE_SCRIPT} --https-base-url <direct-https-base-url> --http-base-url <direct-http-base-url> --host <direct-host> --redirect-host <direct-redirect-host> --spacetime-database <database> --require-wss-upgrade"
|
||
echo "[pingora-direct-enable] dry-run:--apply 后会执行 direct live smoke;--apply 会强制要求 direct live 参数。"
|
||
return
|
||
fi
|
||
|
||
direct_live_args=(
|
||
"${DIRECT_LIVE_SCRIPT}"
|
||
--https-base-url "${DIRECT_HTTPS_BASE_URL}"
|
||
)
|
||
if [[ -n "${DIRECT_HTTP_BASE_URL}" ]]; then
|
||
direct_live_args+=(--http-base-url "${DIRECT_HTTP_BASE_URL}")
|
||
fi
|
||
if [[ -n "${DIRECT_HOST}" ]]; then
|
||
direct_live_args+=(--host "${DIRECT_HOST}")
|
||
fi
|
||
if [[ -n "${DIRECT_REDIRECT_HOST}" ]]; then
|
||
direct_live_args+=(--redirect-host "${DIRECT_REDIRECT_HOST}")
|
||
fi
|
||
if [[ -n "${DIRECT_REDIRECT_BASE_URL}" ]]; then
|
||
direct_live_args+=(--redirect-base-url "${DIRECT_REDIRECT_BASE_URL}")
|
||
fi
|
||
if [[ -n "${DIRECT_PROBE_TOKEN}" ]]; then
|
||
direct_live_args+=(--probe-token "${DIRECT_PROBE_TOKEN}")
|
||
fi
|
||
if [[ -n "${DIRECT_PINGORA_ACCESS_LOG}" ]]; then
|
||
direct_live_args+=(--pingora-access-log "${DIRECT_PINGORA_ACCESS_LOG}")
|
||
fi
|
||
if [[ -n "${DIRECT_ACCESS_LOG_SINCE_LINES}" ]]; then
|
||
direct_live_args+=(--access-log-since-lines "${DIRECT_ACCESS_LOG_SINCE_LINES}")
|
||
fi
|
||
if [[ -n "${DIRECT_SPACETIME_DATABASE}" ]]; then
|
||
direct_live_args+=(--spacetime-database "${DIRECT_SPACETIME_DATABASE}")
|
||
fi
|
||
direct_live_args+=(--require-wss-upgrade)
|
||
if [[ -n "${DIRECT_TIMEOUT_MS}" ]]; then
|
||
direct_live_args+=(--timeout-ms "${DIRECT_TIMEOUT_MS}")
|
||
fi
|
||
direct_live_args+=(--json)
|
||
|
||
print_redacted_command node "${direct_live_args[@]}"
|
||
if [[ "${APPLY}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] dry-run:--apply 后会验证 Pingora HTTPS / HTTP redirect / WSS 直连入口,并解析 direct-access-log 结构化证据。"
|
||
return
|
||
fi
|
||
|
||
set +e
|
||
direct_live_output="$(node "${direct_live_args[@]}")"
|
||
direct_live_status=$?
|
||
set -e
|
||
printf '%s\n' "${direct_live_output}"
|
||
if [[ "${direct_live_status}" -ne 0 ]]; then
|
||
exit "${direct_live_status}"
|
||
fi
|
||
DIRECT_LIVE_OUTPUT="${direct_live_output}" node -- <<'NODE'
|
||
const stdout = process.env.DIRECT_LIVE_OUTPUT || '';
|
||
|
||
const jsonText = extractFirstJsonObject(stdout);
|
||
if (!jsonText) {
|
||
console.error(
|
||
'[pingora-direct-enable] direct live stdout 中未找到 JSON 结果对象,无法确认 direct-access-log 结构化证据。',
|
||
);
|
||
process.exit(1);
|
||
}
|
||
|
||
let parsed;
|
||
try {
|
||
parsed = JSON.parse(jsonText);
|
||
} catch (error) {
|
||
console.error(
|
||
`[pingora-direct-enable] direct live JSON 解析失败: ${error.message}`,
|
||
);
|
||
process.exit(1);
|
||
}
|
||
|
||
const accessLogCheck = parsed?.results?.find(
|
||
(item) => item?.name === 'direct-access-log',
|
||
);
|
||
if (!accessLogCheck) {
|
||
console.error(
|
||
'[pingora-direct-enable] direct live JSON 缺少 direct-access-log 结构化结果。',
|
||
);
|
||
process.exit(1);
|
||
}
|
||
|
||
const checked = toNonNegativeInteger(accessLogCheck.checked);
|
||
const matchedCount = toNonNegativeInteger(accessLogCheck.matchedCount);
|
||
const missingCount = toNonNegativeInteger(accessLogCheck.missingCount);
|
||
const mismatchCount = toNonNegativeInteger(accessLogCheck.mismatchCount);
|
||
const missingDetailsCount = Array.isArray(accessLogCheck.missing)
|
||
? accessLogCheck.missing.length
|
||
: null;
|
||
const mismatchDetailsCount = Array.isArray(accessLogCheck.mismatches)
|
||
? accessLogCheck.mismatches.length
|
||
: null;
|
||
|
||
if (
|
||
checked === null ||
|
||
matchedCount === null ||
|
||
missingCount !== 0 ||
|
||
mismatchCount !== 0 ||
|
||
matchedCount !== checked ||
|
||
missingDetailsCount !== 0 ||
|
||
mismatchDetailsCount !== 0
|
||
) {
|
||
console.error(
|
||
`[pingora-direct-enable] direct-access-log 结构化证据未通过: checked=${checked ?? '-'} matched=${matchedCount ?? '-'} missing=${missingCount ?? '-'} mismatches=${mismatchCount ?? '-'}`,
|
||
);
|
||
process.exit(1);
|
||
}
|
||
|
||
console.log(
|
||
`[pingora-direct-enable] direct-access-log evidence checked=${checked} matched=${matchedCount} missing=0 mismatches=0`,
|
||
);
|
||
|
||
function extractFirstJsonObject(text) {
|
||
const startIndex = text.indexOf('{');
|
||
if (startIndex < 0) {
|
||
return '';
|
||
}
|
||
let depth = 0;
|
||
let inString = false;
|
||
let escaped = false;
|
||
|
||
for (let index = startIndex; index < text.length; index += 1) {
|
||
const char = text[index];
|
||
if (inString) {
|
||
if (escaped) {
|
||
escaped = false;
|
||
} else if (char === '\\') {
|
||
escaped = true;
|
||
} else if (char === '"') {
|
||
inString = false;
|
||
}
|
||
continue;
|
||
}
|
||
if (char === '"') {
|
||
inString = true;
|
||
continue;
|
||
}
|
||
if (char === '{') {
|
||
depth += 1;
|
||
continue;
|
||
}
|
||
if (char === '}') {
|
||
depth -= 1;
|
||
if (depth === 0) {
|
||
return text.slice(startIndex, index + 1);
|
||
}
|
||
}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
function toNonNegativeInteger(value) {
|
||
const number = Number(value);
|
||
if (!Number.isInteger(number) || number < 0) {
|
||
return null;
|
||
}
|
||
return number;
|
||
}
|
||
NODE
|
||
}
|
||
|
||
echo "[pingora-direct-enable] apply=${APPLY} service=${SERVICE_NAME} template=${TEMPLATE_PATH} dropin=${DROPIN_PATH}"
|
||
|
||
if [[ "${APPLY}" != "true" ]]; then
|
||
echo "[pingora-direct-enable] 当前是 dry-run;确认 preflight 通过后追加 --apply。"
|
||
if [[ ! -f "${TEMPLATE_PATH}" ]]; then
|
||
echo "[pingora-direct-enable] dry-run 提示:当前模板不存在,--apply 会失败: ${TEMPLATE_PATH}" >&2
|
||
fi
|
||
fi
|
||
|
||
run_current_release_audit
|
||
run_preflight
|
||
run_cmd install -d -m 0755 "$(dirname "${DROPIN_PATH}")"
|
||
run_cmd install -m 0644 "${TEMPLATE_PATH}" "${DROPIN_PATH}"
|
||
run_systemctl daemon-reload
|
||
run_systemctl restart "${SERVICE_NAME}"
|
||
verify_systemd_dropin
|
||
verify_systemd_exec_start
|
||
verify_service_active_after_restart
|
||
run_direct_live_smoke_after_enable
|
||
|
||
if [[ "${STATUS_AFTER}" == "true" ]]; then
|
||
run_systemctl status "${SERVICE_NAME}" --no-pager
|
||
fi
|
||
|
||
cat <<EOF
|
||
[pingora-direct-enable] 完成。后续请确认:
|
||
- systemctl cat ${SERVICE_NAME} 包含 AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||
- systemctl show ${SERVICE_NAME} --property=ExecStart --value --no-pager 指向 current release 的 pingora-gateway
|
||
- systemctl is-active ${SERVICE_NAME} 为 active
|
||
- node ${CURRENT_RELEASE_AUDIT_SCRIPT} --release-root ${CURRENT_RELEASE_ROOT} --require-pingora-gateway --systemd-show --systemd-service ${SERVICE_NAME} 已通过
|
||
- npm run check:pingora-direct-preflight -- --env-file /etc/genarrative/pingora-gateway.env --require-live-env --systemd-cat --check-cert-readable --check-service-env-file --check-service-user-cert-readable --check-service-binary-executable --check-ports-free 已通过
|
||
- node ${DIRECT_LIVE_SCRIPT} --https-base-url ${DIRECT_HTTPS_BASE_URL:-<direct-https-base-url>} --http-base-url ${DIRECT_HTTP_BASE_URL:-<direct-http-base-url>} --host ${DIRECT_HOST:-<direct-host>} --redirect-host ${DIRECT_REDIRECT_HOST:-<direct-redirect-host>} ${DIRECT_REDIRECT_BASE_URL:+--redirect-base-url ${DIRECT_REDIRECT_BASE_URL} }--pingora-access-log ${DIRECT_PINGORA_ACCESS_LOG:-<pingora-access-log>} --spacetime-database ${DIRECT_SPACETIME_DATABASE:-<database>} --require-wss-upgrade --json 已通过,且 direct-access-log 结构化证据 matched=checked、missing=0、mismatches=0
|
||
EOF
|