文件
hyb-oa/deploy/trialrun/install-offhost-app-health-monitor.sh
T

159 行
6.0 KiB
Bash
可执行文件

#!/usr/bin/env bash
set -euo pipefail
READY_URL="${READY_URL:-https://oa.hyinda.com/ready}"
PROBE_SOURCE="${PROBE_SOURCE:-}"
PROBE_TARGET="${PROBE_TARGET:-/usr/local/sbin/hyb-oa-public-app-health}"
ALERT_WEBHOOK_FILE="${ALERT_WEBHOOK_FILE:-}"
ALERT_HELPER_SOURCE="${ALERT_HELPER_SOURCE:-}"
ALERT_HELPER_TARGET="${ALERT_HELPER_TARGET:-/usr/local/sbin/hyb-oa-wecom-group-alert}"
STATE_DIR="${STATE_DIR:-/var/lib/hyb-oa-app-health}"
FAILURE_THRESHOLD="${FAILURE_THRESHOLD:-2}"
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-10}"
SERVICE_NAME="${SERVICE_NAME:-hyb-oa-public-app-health}"
SYSTEMD_DIR="${SYSTEMD_DIR:-/etc/systemd/system}"
MODE="${1:-install}"
fail() {
echo "[app-health-installer][ERROR] $1" >&2
exit 1
}
need_root() {
[[ "$(id -u)" == "0" ]] || fail "root privileges are required"
}
validate_absolute_path() {
local name="$1"
local value="$2"
if [[ -z "$value" || "$value" != /* || ! "$value" =~ ^/[A-Za-z0-9._/-]+$ ]]; then
fail "$name must be an explicit safe absolute path"
fi
if [[ "$value" == "/" || "$value" == */ || "$value" == *"//"* \
|| "/$value/" == *"/../"* || "/$value/" == *"/./"* ]]; then
fail "$name contains an unsafe path segment"
fi
}
validate_managed_targets() {
[[ "$PROBE_TARGET" == "/usr/local/sbin/hyb-oa-public-app-health" ]] \
|| fail "PROBE_TARGET must remain /usr/local/sbin/hyb-oa-public-app-health"
[[ "$ALERT_HELPER_TARGET" == "/usr/local/sbin/hyb-oa-wecom-group-alert" ]] \
|| fail "ALERT_HELPER_TARGET must remain /usr/local/sbin/hyb-oa-wecom-group-alert"
[[ "$STATE_DIR" == "/var/lib/hyb-oa-app-health" ]] \
|| fail "STATE_DIR must remain /var/lib/hyb-oa-app-health"
[[ "$SYSTEMD_DIR" == "/etc/systemd/system" ]] \
|| fail "SYSTEMD_DIR must remain /etc/systemd/system"
[[ "$SERVICE_NAME" == "hyb-oa-public-app-health" ]] \
|| fail "SERVICE_NAME must remain hyb-oa-public-app-health"
}
validate_inputs() {
local name value
for name in PROBE_SOURCE PROBE_TARGET ALERT_WEBHOOK_FILE ALERT_HELPER_SOURCE ALERT_HELPER_TARGET STATE_DIR SYSTEMD_DIR; do
value="${!name:-}"
validate_absolute_path "$name" "$value"
done
validate_managed_targets
[[ "$READY_URL" =~ ^https://[A-Za-z0-9.-]+(:([0-9]{1,5}))?/ready$ ]] \
|| fail "READY_URL must be an HTTPS /ready endpoint without query or fragment"
if [[ -n "${BASH_REMATCH[2]:-}" && ("${BASH_REMATCH[2]}" -lt 1 || "${BASH_REMATCH[2]}" -gt 65535) ]]; then
fail "READY_URL port is invalid"
fi
[[ "$FAILURE_THRESHOLD" == "2" ]] || fail "FAILURE_THRESHOLD must remain 2"
[[ "$TIMEOUT_SECONDS" =~ ^([1-9]|[12][0-9]|30)$ ]] || fail "TIMEOUT_SECONDS must be between 1 and 30"
[[ -f "$PROBE_SOURCE" && ! -L "$PROBE_SOURCE" ]] || fail "probe source is missing"
[[ -f "$ALERT_HELPER_SOURCE" && ! -L "$ALERT_HELPER_SOURCE" ]] || fail "alert helper source is missing"
[[ -f "$ALERT_WEBHOOK_FILE" && ! -L "$ALERT_WEBHOOK_FILE" \
&& "$(stat -c %a "$ALERT_WEBHOOK_FILE")" == "600" \
&& "$(stat -c %u "$ALERT_WEBHOOK_FILE")" == "0" ]] \
|| fail "alert webhook file must be root-owned with mode 0600"
[[ -d "$SYSTEMD_DIR" && ! -L "$SYSTEMD_DIR" ]] || fail "systemd directory is invalid"
command -v python3 >/dev/null 2>&1 || fail "python3 is required"
command -v systemctl >/dev/null 2>&1 || fail "systemctl is required"
}
install_monitor() {
need_root
validate_inputs
systemctl disable --now "${SERVICE_NAME}.timer" >/dev/null 2>&1 || true
systemctl stop "${SERVICE_NAME}.service" >/dev/null 2>&1 || true
install -o root -g root -m 0755 "$PROBE_SOURCE" "$PROBE_TARGET"
install -o root -g root -m 0755 "$ALERT_HELPER_SOURCE" "$ALERT_HELPER_TARGET"
mkdir -p "$STATE_DIR"
[[ -d "$STATE_DIR" && ! -L "$STATE_DIR" ]] || fail "state directory is invalid"
chown root:root "$STATE_DIR"
chmod 0700 "$STATE_DIR"
cat >"$SYSTEMD_DIR/${SERVICE_NAME}.service" <<SERVICE
[Unit]
Description=hyb-oa independent public application readiness probe
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
UMask=0077
ExecStart=/usr/bin/python3 ${PROBE_TARGET} --ready-url ${READY_URL} --state-dir ${STATE_DIR} --webhook-file ${ALERT_WEBHOOK_FILE} --alert-helper ${ALERT_HELPER_TARGET} --failure-threshold ${FAILURE_THRESHOLD} --timeout-seconds ${TIMEOUT_SECONDS}
TimeoutStartSec=30
SERVICE
cat >"$SYSTEMD_DIR/${SERVICE_NAME}.timer" <<TIMER
[Unit]
Description=Check hyb-oa public application readiness every five minutes
[Timer]
OnCalendar=*:0/5
Persistent=true
AccuracySec=10s
Unit=${SERVICE_NAME}.service
[Install]
WantedBy=timers.target
TIMER
chmod 0644 "$SYSTEMD_DIR/${SERVICE_NAME}.service" "$SYSTEMD_DIR/${SERVICE_NAME}.timer"
systemctl daemon-reload
echo "[app-health-installer][PASS] disabled application health monitor installed"
}
enable_monitor() {
install_monitor
systemctl enable --now "${SERVICE_NAME}.timer"
echo "[app-health-installer][PASS] application health timer enabled"
}
uninstall_monitor() {
need_root
validate_absolute_path PROBE_TARGET "$PROBE_TARGET"
validate_absolute_path SYSTEMD_DIR "$SYSTEMD_DIR"
[[ "$PROBE_TARGET" == "/usr/local/sbin/hyb-oa-public-app-health" ]] \
|| fail "PROBE_TARGET must remain /usr/local/sbin/hyb-oa-public-app-health"
[[ "$SYSTEMD_DIR" == "/etc/systemd/system" ]] \
|| fail "SYSTEMD_DIR must remain /etc/systemd/system"
[[ "$SERVICE_NAME" == "hyb-oa-public-app-health" ]] \
|| fail "SERVICE_NAME must remain hyb-oa-public-app-health"
systemctl disable --now "${SERVICE_NAME}.timer" >/dev/null 2>&1 || true
systemctl stop "${SERVICE_NAME}.service" >/dev/null 2>&1 || true
rm -f -- "$SYSTEMD_DIR/${SERVICE_NAME}.timer" "$SYSTEMD_DIR/${SERVICE_NAME}.service" "$PROBE_TARGET"
systemctl daemon-reload
echo "[app-health-installer][PASS] monitor removed; state and shared alert files retained"
}
case "$MODE" in
install)
install_monitor
;;
enable)
enable_monitor
;;
uninstall|--uninstall)
uninstall_monitor
;;
--help|-h)
echo "Usage: <explicit probe/webhook/helper paths> bash install-offhost-app-health-monitor.sh [install|enable|uninstall]"
;;
*)
fail "unsupported mode"
;;
esac