Files
Genarrative/scripts/deploy/pingora-realpath-canary-disable.sh
T
kdletters 123d4ada01 脚本化 Pingora realpath canary 启停
新增 realpath canary 启用和关闭脚本

将脚本纳入 release、deploy、Jenkins 和 current release 自审

补充脚本化 canary 文档和生产运维护栏

增加 realpath canary 启停自测和发布部署护栏
2026-06-17 23:45:58 +08:00

198 lines
5.5 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
TARGET_PATH="${GENARRATIVE_PINGORA_REALPATH_CANARY_TARGET_PATH:-/etc/nginx/conf.d/zz-genarrative-pingora-realpath-canary.conf}"
NGINX_BINARY="${GENARRATIVE_NGINX_BINARY:-nginx}"
NGINX_SERVICE="${GENARRATIVE_NGINX_SERVICE:-nginx.service}"
SYSTEMCTL_BINARY="${GENARRATIVE_SYSTEMCTL_BINARY:-systemctl}"
APPLY="false"
STATUS_AFTER="true"
usage() {
cat <<'EOF'
用法:
scripts/deploy/pingora-realpath-canary-disable.sh [--apply] [--target-path <path>] [--nginx-binary <path|name>] [--nginx-service <unit>] [--systemctl-binary <path|name>] [--no-status]
说明:
关闭 Nginx -> Pingora 真实路径 canary:删除
/etc/nginx/conf.d/zz-genarrative-pingora-realpath-canary.conf,执行 nginx -t
再 reload nginx。默认 dry-run,必须显式传 --apply 才会修改系统。
如果 nginx -t 或 reload 失败,脚本会恢复删除前的目标文件。
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
--apply)
APPLY="true"
shift
;;
--target-path)
TARGET_PATH="${2:-}"
if [[ -z "${TARGET_PATH}" ]]; then
echo "[pingora-realpath-canary-disable] --target-path 缺少参数" >&2
exit 1
fi
shift 2
;;
--nginx-binary)
NGINX_BINARY="${2:-}"
if [[ -z "${NGINX_BINARY}" ]]; then
echo "[pingora-realpath-canary-disable] --nginx-binary 缺少参数" >&2
exit 1
fi
shift 2
;;
--nginx-service)
NGINX_SERVICE="${2:-}"
if [[ -z "${NGINX_SERVICE}" ]]; then
echo "[pingora-realpath-canary-disable] --nginx-service 缺少参数" >&2
exit 1
fi
shift 2
;;
--systemctl-binary)
SYSTEMCTL_BINARY="${2:-}"
if [[ -z "${SYSTEMCTL_BINARY}" ]]; then
echo "[pingora-realpath-canary-disable] --systemctl-binary 缺少参数" >&2
exit 1
fi
shift 2
;;
--no-status)
STATUS_AFTER="false"
shift
;;
*)
echo "[pingora-realpath-canary-disable] 未知参数: $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-realpath-canary-disable] ${label} 不能包含换行或 NUL 字符。" >&2
exit 1
fi
}
is_filesystem_root_path() {
local value="$1"
local without_slashes="${value//\//}"
[[ -n "${value}" && -z "${without_slashes}" ]]
}
require_absolute_path() {
local label="$1"
local value="$2"
if [[ "${value}" != /* ]]; then
echo "[pingora-realpath-canary-disable] ${label} 必须是绝对路径。" >&2
exit 1
fi
if is_filesystem_root_path "${value}"; then
echo "[pingora-realpath-canary-disable] ${label} 不能是文件系统根目录。" >&2
exit 1
fi
}
validate_command_or_absolute_path() {
local label="$1"
local value="$2"
if [[ "${value}" == */* ]]; then
require_absolute_path "${label}" "${value}"
fi
}
print_command() {
printf '+'
for arg in "$@"; do
printf ' %q' "${arg}"
done
printf '\n'
}
run_or_print() {
if [[ "${APPLY}" == "true" ]]; then
"$@"
else
print_command "$@"
fi
}
restore_previous() {
local backup_path="$1"
cp -p -- "${backup_path}" "${TARGET_PATH}"
}
rollback_after_failure() {
local backup_path="$1"
local reason="$2"
echo "[pingora-realpath-canary-disable] ${reason},恢复删除前配置。" >&2
restore_previous "${backup_path}"
"${NGINX_BINARY}" -t >/dev/null 2>&1 || true
"${SYSTEMCTL_BINARY}" reload "${NGINX_SERVICE}" >/dev/null 2>&1 || true
}
reject_control_characters "--target-path" "${TARGET_PATH}"
reject_control_characters "--nginx-binary" "${NGINX_BINARY}"
reject_control_characters "--nginx-service" "${NGINX_SERVICE}"
reject_control_characters "--systemctl-binary" "${SYSTEMCTL_BINARY}"
require_absolute_path "--target-path" "${TARGET_PATH}"
validate_command_or_absolute_path "--nginx-binary" "${NGINX_BINARY}"
validate_command_or_absolute_path "--systemctl-binary" "${SYSTEMCTL_BINARY}"
TARGET_DIR="$(dirname -- "${TARGET_PATH}")"
if [[ "${APPLY}" == "true" && ( -L "${TARGET_DIR}" || -L "${TARGET_PATH}" ) ]]; then
echo "[pingora-realpath-canary-disable] 目标目录或目标文件不能是符号链接。" >&2
exit 1
fi
if [[ "${APPLY}" != "true" ]]; then
echo "[pingora-realpath-canary-disable] dry-run:将删除 realpath canary ${TARGET_PATH}。"
print_command rm -f -- "${TARGET_PATH}"
run_or_print "${NGINX_BINARY}" -t
run_or_print "${SYSTEMCTL_BINARY}" reload "${NGINX_SERVICE}"
exit 0
fi
if [[ ! -e "${TARGET_PATH}" ]]; then
echo "[pingora-realpath-canary-disable] 目标文件不存在,视为已关闭: ${TARGET_PATH}"
if [[ "${STATUS_AFTER}" == "true" ]]; then
"${SYSTEMCTL_BINARY}" is-active "${NGINX_SERVICE}"
fi
exit 0
fi
if [[ ! -f "${TARGET_PATH}" ]]; then
echo "[pingora-realpath-canary-disable] 目标存在但不是普通文件: ${TARGET_PATH}" >&2
exit 1
fi
backup_path="$(mktemp "${TARGET_DIR}/.genarrative-pingora-realpath-canary.disable.backup.XXXXXX")"
trap 'rm -f -- "${backup_path}"' EXIT
cp -p -- "${TARGET_PATH}" "${backup_path}"
rm -f -- "${TARGET_PATH}"
if ! "${NGINX_BINARY}" -t; then
rollback_after_failure "${backup_path}" "nginx -t 失败"
exit 1
fi
if ! "${SYSTEMCTL_BINARY}" reload "${NGINX_SERVICE}"; then
rollback_after_failure "${backup_path}" "reload ${NGINX_SERVICE} 失败"
exit 1
fi
if [[ "${STATUS_AFTER}" == "true" ]]; then
"${SYSTEMCTL_BINARY}" is-active "${NGINX_SERVICE}"
fi
echo "[pingora-realpath-canary-disable] 已关闭 realpath canary: ${TARGET_PATH}"