235 lines
7.0 KiB
Bash
Executable File
235 lines
7.0 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
|
|
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" ;;
|
|
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
|