hy-app-monitor/localbox/check_local_services.sh
2026-05-09 10:40:17 +08:00

237 lines
7.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common.sh"
load_local_env
wait_for_docker
APP_SERVICES=(
auth
gateway
wallet
other
live
order
console
scheduling
external
visual-monitor
game-fruit
golang
)
INFRA_SERVICES=(
mysql
redis
mongo
nacos
zookeeper
)
if ! local_rocketmq_disabled; then
INFRA_SERVICES+=(
rocketmq-namesrv
rocketmq-broker
rocketmq-proxy
)
fi
FAILURES=0
container_name_for_service() {
case "$1" in
visual-monitor) printf '%s\n' "chatapp3-local-visual-monitor" ;;
game-fruit) printf '%s\n' "chatapp3-local-game-fruit" ;;
rocketmq-namesrv) printf '%s\n' "chatapp3-local-rocketmq-namesrv" ;;
rocketmq-broker) printf '%s\n' "chatapp3-local-rocketmq-broker" ;;
rocketmq-proxy) printf '%s\n' "chatapp3-local-rocketmq-proxy" ;;
*) printf '%s\n' "chatapp3-local-$1" ;;
esac
}
health_url_for_service() {
local service="$1"
case "$service" in
gateway)
printf 'http://127.0.0.1:%s/actuator/health\n' "$(service_port "$service")"
;;
console)
printf 'http://127.0.0.1:%s/console/actuator/health\n' "$(service_port "$service")"
;;
golang)
printf 'http://127.0.0.1:%s/health\n' "$(service_port "$service")"
;;
*)
printf 'http://127.0.0.1:%s/actuator/health\n' "$(service_port "$service")"
;;
esac
}
http_probe() {
local url="$1"
local body_file http_code
body_file="$(mktemp)"
http_code="$(curl -sS --max-time 5 -o "$body_file" -w '%{http_code}' "$url" || true)"
printf '%s\n' "$http_code"
cat "$body_file"
rm -f "$body_file"
}
print_row() {
printf '%-16s %-10s %-12s %s\n' "$1" "$2" "$3" "$4"
}
published_host_port() {
local container_name="$1"
local target_port="$2"
docker port "$container_name" "$target_port" 2>/dev/null | sed -n '1s/.*://p'
}
probe_app_service() {
local service="$1"
local container_name container_state health_url
local probe_payload http_code body status detail
container_name="$(container_name_for_service "$service")"
container_state="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container_name" 2>/dev/null || printf 'missing')"
health_url="$(health_url_for_service "$service")"
probe_payload="$(http_probe "$health_url")"
http_code="$(printf '%s\n' "$probe_payload" | sed -n '1p')"
body="$(printf '%s\n' "$probe_payload" | sed '1d')"
status="FAIL"
detail="container=${container_state} http=${http_code}"
if [ "$http_code" = "200" ]; then
if [ "$service" = "golang" ]; then
status="OK"
detail="container=${container_state} http=200 path=/health"
else
local actuator_status reason
actuator_status="$(printf '%s' "$body" | jq -r '.status // empty' 2>/dev/null || true)"
if [ "$actuator_status" = "UP" ]; then
status="OK"
detail="container=${container_state} actuator=UP"
else
reason="$(printf '%s' "$body" | jq -r '.components.refreshScope.details.error // .components.db.details.error // .error // empty' 2>/dev/null || true)"
detail="container=${container_state} actuator=${actuator_status:-unknown}"
if [ -n "$reason" ]; then
detail="$detail reason=$(printf '%s' "$reason" | tr '\n' ' ' | cut -c1-120)"
fi
fi
fi
else
local reason
reason="$(printf '%s' "$body" | jq -r '.errorMsg // .message // .status // empty' 2>/dev/null || true)"
if [ -n "$reason" ]; then
detail="$detail reason=$(printf '%s' "$reason" | tr '\n' ' ' | cut -c1-120)"
fi
fi
if [ "$status" != "OK" ]; then
FAILURES=$((FAILURES + 1))
fi
print_row "$service" "$status" "$container_state" "$detail"
}
probe_infra_service() {
local service="$1"
local container_name container_state status detail
container_name="$(container_name_for_service "$service")"
container_state="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container_name" 2>/dev/null || printf 'missing')"
status="FAIL"
detail="container=${container_state}"
case "$service" in
nacos)
local probe_payload http_code body nacos_status
probe_payload="$(http_probe "http://127.0.0.1:${LIKEI_LOCAL_NACOS_PORT}/nacos/actuator/health")"
http_code="$(printf '%s\n' "$probe_payload" | sed -n '1p')"
body="$(printf '%s\n' "$probe_payload" | sed '1d')"
nacos_status="$(printf '%s' "$body" | jq -r '.status // empty' 2>/dev/null || true)"
if [ "$http_code" = "200" ] && [ "$nacos_status" = "UP" ]; then
status="OK"
detail="container=${container_state} actuator=UP"
else
detail="container=${container_state} http=${http_code} actuator=${nacos_status:-unknown}"
fi
;;
zookeeper)
local zk_host_port
zk_host_port="$(published_host_port "$container_name" "2181/tcp")"
if [ -z "$zk_host_port" ]; then
zk_host_port="${LIKEI_LOCAL_ZOOKEEPER_EXPOSE_PORT}"
fi
if nc -z 127.0.0.1 "$zk_host_port" >/dev/null 2>&1; then
status="OK"
detail="container=${container_state} tcp=open port=${zk_host_port}"
else
detail="container=${container_state} tcp=not_ready port=${zk_host_port}"
fi
;;
rocketmq-namesrv)
if nc -z 127.0.0.1 "${LIKEI_LOCAL_ROCKETMQ_NAMESRV_PORT}" >/dev/null 2>&1; then
status="OK"
detail="container=${container_state} tcp=open port=${LIKEI_LOCAL_ROCKETMQ_NAMESRV_PORT}"
else
detail="container=${container_state} tcp=not_ready port=${LIKEI_LOCAL_ROCKETMQ_NAMESRV_PORT}"
fi
;;
rocketmq-broker)
if docker exec chatapp3-local-rocketmq-broker sh mqadmin clusterList -n rocketmq-namesrv:9876 2>/dev/null | grep -q "DefaultCluster"; then
status="OK"
detail="container=${container_state} cluster=DefaultCluster"
else
detail="container=${container_state} cluster=not_ready"
fi
;;
rocketmq-proxy)
if nc -z 127.0.0.1 "${LIKEI_LOCAL_ROCKETMQ_PROXY_GRPC_PORT}" >/dev/null 2>&1; then
status="OK"
detail="container=${container_state} tcp=open port=${LIKEI_LOCAL_ROCKETMQ_PROXY_GRPC_PORT}"
else
detail="container=${container_state} tcp=not_ready port=${LIKEI_LOCAL_ROCKETMQ_PROXY_GRPC_PORT}"
fi
;;
*)
if [ "$container_state" = "healthy" ] || [ "$container_state" = "running" ]; then
status="OK"
detail="container=${container_state}"
fi
;;
esac
if [ "$status" != "OK" ]; then
FAILURES=$((FAILURES + 1))
fi
print_row "$service" "$status" "$container_state" "$detail"
}
echo "App Services"
print_row "SERVICE" "RESULT" "CONTAINER" "DETAIL"
for service in "${APP_SERVICES[@]}"; do
probe_app_service "$service"
done
echo
echo "Infra Services"
print_row "SERVICE" "RESULT" "CONTAINER" "DETAIL"
for service in "${INFRA_SERVICES[@]}"; do
probe_infra_service "$service"
done
echo
if [ "$FAILURES" -eq 0 ]; then
echo "SUMMARY: all checked local backend services are healthy"
else
echo "SUMMARY: $FAILURES service(s) need attention"
exit 1
fi