Files
deploy-test/status.sh
2026-04-21 12:24:04 +07:00

243 lines
12 KiB
Bash
Executable File
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
# =============================================================================
# status.sh — 查看所有服务运行状态
#
# 显示内容:
# - Docker 容器状态Redis/Kafka/Etcd
# - 远程服务配置摘要MongoDB/S3
# - 后端服务进程状态PID + 监听端口)
# =============================================================================
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh"
if [[ -f "$ENV_FILE" ]]; then
set -a
# shellcheck source=/dev/null
source "$ENV_FILE"
set +a
fi
DEPLOY_TEST_IP="${DEPLOY_TEST_IP:-127.0.0.1}"
normalize_pc_proxy_env
header "服务运行状态"
# ── Docker 基础设施 ───────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ Docker 基础设施 ]${NC}"
print_container_status "Redis" "dev-redis" "${REDIS_PORT:-6379}"
print_container_status "Kafka" "dev-kafka" "${KAFKA_PORT:-9092}"
printf " ${CYAN}${NC} %-10s Kafka 外网 bootstrapEXTERNAL%s:%s TCP PLAINTEXT\n" "" "${DEPLOY_TEST_IP:-?}" "${KAFKA_EXTERNAL_PORT:-9094}"
print_container_status "Etcd" "dev-etcd" "${ETCD_PORT:-2379}"
print_container_status "MinIO" "dev-minio" "${MINIO_API_PORT:-9000}"
print_container_status "LiveKit" "dev-livekit" "7880"
printf " ${CYAN}${NC} %-10s 公网 %s:50000-51000/udp (WebRTC)\n" "" "${LIVEKIT_NODE_IP:-?}"
# ── Etcd RPC 注册 ─────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ Etcd RPC 注册 ]${NC}"
ETCD_ENDPOINT="127.0.0.1:${ETCD_PORT:-2379}"
if ! command -v etcdctl &>/dev/null; then
printf " ${YELLOW}${NC} %-18s %s\n" "etcdctl" "未安装,请执行: sudo ./deploy-test/00-init-tools.sh etcdctl"
else
if ETCD_KEYS=$(ETCDCTL_API=3 etcdctl --endpoints="$ETCD_ENDPOINT" get --prefix "" --keys-only 2>&1); then
if [[ -z "$ETCD_KEYS" ]]; then
printf " ${YELLOW}${NC} %-18s %s\n" "registry" "Etcd 可访问,但当前无注册 key"
else
OPENIM_STANDALONE_RPC_SERVICES=(
auth-rpc-service
user-rpc-service
friend-rpc-service
group-rpc-service
msg-rpc-service
conversation-rpc-service
third-rpc-service
push-rpc-service
messagegateway-rpc-service
)
INDEPENDENT_RPC_SERVICES=(
chat-rpc-service
admin-rpc-service
bot-rpc-service
)
echo -e " ${CYAN}OpenIM standalone 内部 RPC单进程内调用不要求 Etcd 注册):${NC}"
for svc in "${OPENIM_STANDALONE_RPC_SERVICES[@]}"; do
count=$(printf '%s\n' "$ETCD_KEYS" | grep -c "$svc" || true)
if [[ "$count" -gt 0 ]]; then
printf " ${GREEN}${NC} %-28s %s key(s)\n" "$svc" "$count"
else
printf " ${CYAN}${NC} %-28s %s\n" "$svc" "standalone 进程内"
fi
done
echo -e " ${CYAN}独立进程 RPC应注册到 Etcd${NC}"
found_required_rpc=0
missing_required_rpc=0
for svc in "${INDEPENDENT_RPC_SERVICES[@]}"; do
count=$(printf '%s\n' "$ETCD_KEYS" | grep -c "$svc" || true)
if [[ "$count" -gt 0 ]]; then
found_required_rpc=1
printf " ${GREEN}${NC} %-28s %s key(s)\n" "$svc" "$count"
else
missing_required_rpc=1
printf " ${YELLOW}${NC} %-28s %s\n" "$svc" "未注册"
fi
done
echo -e " ${CYAN}原始注册 key过滤 rpc/service/openim/chat/admin 等关键词,最多 80 行):${NC}"
filtered_keys=$(printf '%s\n' "$ETCD_KEYS" | grep -Ei 'rpc|service|openim|chat|admin|auth|user|friend|group|msg|conversation|third|push|gateway|bot' | head -80 || true)
if [[ -n "$filtered_keys" ]]; then
printf '%s\n' "$filtered_keys" | sed 's/^/ /'
else
echo " (未匹配到 RPC 相关 key)"
fi
if [[ "$found_required_rpc" -eq 0 ]]; then
warn " 未发现独立进程 RPC 注册chat-api/admin-api 调 RPC 时可能出现 name resolver error: produced zero addresses"
elif [[ "$missing_required_rpc" -eq 1 ]]; then
warn " 存在独立进程 RPC 未注册;如果对应 API 调用失败,请优先检查该 RPC 进程日志"
fi
fi
else
printf " ${RED}${NC} %-18s %s\n" "etcd" "不可访问: $ETCD_ENDPOINT"
printf "%s\n" "$ETCD_KEYS" | sed 's/^/ /'
fi
fi
# ── 远程服务 ─────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ 远程服务(连接配置)]${NC}"
printf " ${CYAN}${NC} %-10s %s\n" "MongoDB" \
"${MONGO_HOST:-?}:${MONGO_PORT:-27017}/${MONGO_DATABASE:-?} (authSource=${MONGO_AUTHSOURCE:-?})"
printf " ${CYAN}${NC} %-10s %s\n" "MinIO" \
"bucket=${MINIO_BUCKET:-?} external=${MINIO_EXTERNAL_ADDRESS:-?}"
# ── 后端服务 ─────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ 后端服务 ]${NC}"
print_svc_status "openim-server" ":10002 (API) :10001 (MsgGateway WS)"
print_svc_status "chat-rpc" "内部 RPC → Etcd"
print_svc_status "admin-rpc" "内部 RPC → Etcd"
print_svc_status "chat-api" ":10008"
print_svc_status "admin-api" ":10009"
print_svc_status "meetingmsg" ":8000 (WS)"
print_svc_status "livecloud" ":8080"
print_svc_status "livestream" ":8888"
print_svc_status "build-server" ":8281"
# ── Nginx API / WebSocket 网关 ─────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ Nginx 网关PC API / WebSocket]${NC}"
if command -v curl &>/dev/null && [[ -n "${PC_BACKEND_ORIGIN:-}" ]]; then
PC_BACKEND_ORIGIN="${PC_BACKEND_ORIGIN%/}"
curl_tls=()
[[ "$PC_BACKEND_ORIGIN" == https://* ]] && curl_tls=(-k)
if curl "${curl_tls[@]}" -fsS --max-time 3 "${PC_BACKEND_ORIGIN}/nginx-health" >/dev/null 2>&1; then
printf " ${GREEN}${NC} %-14s %s\n" "nginx-health" "${PC_BACKEND_ORIGIN}/nginx-health"
else
printf " ${RED}${NC} %-14s %s\n" "nginx-health" "${PC_BACKEND_ORIGIN}/nginx-health 不可达"
echo " 请执行: sudo ./deploy-test/00-init-tools.sh nginx并确认安全组/防火墙放行 TCP 80"
fi
gateway_host=$(printf '%s' "$PC_BACKEND_ORIGIN" | sed -E 's#^https?://([^/]+).*#\1#')
if [[ "$PC_BACKEND_ORIGIN" == https://* ]]; then
default_ws_url="wss://${gateway_host}/msg_gateway"
else
default_ws_url="ws://${gateway_host}/msg_gateway"
fi
echo " PC IM API: ${PC_VITE_API_URL:-${PC_BACKEND_ORIGIN}/api/im}"
echo " PC User API: ${PC_VITE_USER_URL:-${PC_BACKEND_ORIGIN}/api/user}"
echo " PC Chat API: ${PC_VITE_CHAT_URL:-${PC_BACKEND_ORIGIN}/api/chat}"
echo " PC Admin API: ${PC_VITE_ADMIN_URL:-${PC_BACKEND_ORIGIN}/api/admin}"
echo " PC WebSocket: ${PC_VITE_WS_URL:-$default_ws_url}"
echo " PC 页面入口: ${PC_BACKEND_ORIGIN}/ (外部 HTTPS → 本机 Nginx :80 → /app/pc/dist)"
echo " Nginx 日志: /var/log/nginx/openim-pc-proxy-access.log"
pc_probe_msg_gateway "$PC_BACKEND_ORIGIN"
else
printf " ${YELLOW}${NC} %-14s %s\n" "nginx-health" "跳过(未安装 curl 或未设置 PC_BACKEND_ORIGIN"
fi
# ── 静态前端 ─────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ 静态前端 ]${NC}"
print_static_site_status() {
local label="$1" dist_file="$2" build_hint="$3" host_header="$4" access_url="$5"
local body title
if [[ -f "$dist_file" ]]; then
printf " ${GREEN}${NC} %-14s %s\n" "${label}-dist" "$dist_file"
else
printf " ${YELLOW}${NC} %-14s %s\n" "${label}-dist" "未构建(执行 ${build_hint}"
fi
if command -v curl &>/dev/null; then
if curl -fsS --max-time 3 -H "Host: ${host_header}" http://127.0.0.1/nginx-health >/dev/null 2>&1; then
printf " ${GREEN}${NC} %-14s %s\n" "${label}-nginx" "$access_url"
body="$(curl -fsS --max-time 5 -H "Host: ${host_header}" http://127.0.0.1/ 2>/dev/null || true)"
if [[ -n "$body" ]] && printf '%s' "$body" | grep -qi "<html"; then
title="$(printf '%s' "$body" | grep -oiE '<title>[^<]*</title>' | head -1 | sed -E 's#</?title>##g' || true)"
if [[ -n "$title" ]]; then
printf " ${CYAN}${NC} %-14s %s\n" "${label}-title" "$title"
else
printf " ${CYAN}${NC} %-14s %s\n" "${label}-title" "(未解析到 <title>)"
fi
else
printf " ${YELLOW}${NC} %-14s %s\n" "${label}-title" "首页返回异常,未识别为 HTML"
fi
else
printf " ${YELLOW}${NC} %-14s %s\n" "${label}-nginx" "不可达(执行 sudo ./deploy-test/00-init-tools.sh nginx"
fi
fi
}
print_static_site_status "pc" "$ROOT_DIR/pc/dist/index.html" "./deploy-test/08-build-static-frontend.sh pc" "${PC_PROXY_DOMAIN}" "${PC_BACKEND_ORIGIN}/"
print_static_site_status "cms" "$ROOT_DIR/cms/dist/index.html" "./deploy-test/08-build-static-frontend.sh cms" "cms-jack.imharry.work" "http://cms-jack.imharry.work/"
print_static_site_status "build-cms" "$ROOT_DIR/build-cms/dist/index.html" "./deploy-test/08-build-static-frontend.sh build-cms" "build-jack.imharry.work" "http://build-jack.imharry.work/"
print_static_site_status "build-down" "$ROOT_DIR/build-down/dist/index.html" "./deploy-test/08-build-static-frontend.sh build-down" "down-jack.imharry.work" "http://down-jack.imharry.work/"
# ── 前端开发服务器 ─────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ 前端开发服务器 ]${NC}"
fe_port_desc() {
case "$1" in
meetingh5) echo "5188" ;;
h5) echo "3003" ;;
*) echo "?" ;;
esac
}
for fe in meetingh5 h5; do
pidfile="$PID_DIR/fe-${fe}.pid"
logfile="$LOG_DIR/fe-${fe}.log"
port_desc="$(fe_port_desc "$fe")"
if [[ -f "$pidfile" ]] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
printf " ${GREEN}${NC} %-14s PID=%-7s :%s\n" "$fe" "$(cat "$pidfile")" "$port_desc"
else
printf " ${RED}${NC} %-14s 未运行 :%s\n" "$fe" "$port_desc"
fi
done
# ── 端口占用检查 ──────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ 端口占用 ]${NC}"
PORTS=(10002 10001 10008 10009 8000 8080 8888 8281 5188 3003)
for port in "${PORTS[@]}"; do
pid=$(lsof -ti :"$port" 2>/dev/null | head -1 || true)
if [[ -n "$pid" ]]; then
cmd=$(ps -p "$pid" -o comm= 2>/dev/null || echo "?")
printf " ${GREEN}${NC} :%d PID=%-6s (%s)\n" "$port" "$pid" "$cmd"
else
printf " ${YELLOW}${NC} :%d (未监听)\n" "$port"
fi
done
# ── 快速操作提示 ──────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}[ 快捷命令 ]${NC}"
echo " ./deploy-test/logs.sh <service> 查看日志(支持前端: meetingh5/h5"
echo " ./deploy-test/restart.sh <service> 重启后端服务"
echo " ./deploy-test/restart.sh <svc> --build 重编译并重启"
echo " ./deploy-test/07-start-frontend.sh 启动开发态前端"
echo " ./deploy-test/08-build-static-frontend.sh 构建 pc/cms/build-cms/build-down 静态资源"
echo " sudo ./deploy-test/dt.sh fe-publish 构建静态前端 + 更新 Nginx + 校验"
echo " ./deploy-test/stop-frontend.sh 停止前端服务"
echo " ./deploy-test/check-conn.sh 验证 MongoDB/S3 连接"
echo ""