init
This commit is contained in:
225
common.sh
Executable file
225
common.sh
Executable file
@@ -0,0 +1,225 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# common.sh — 公共函数库,供各子脚本 source 引入
|
||||
# 不可直接执行
|
||||
# =============================================================================
|
||||
|
||||
# 防止重复加载
|
||||
[[ -n "${_COMMON_LOADED:-}" ]] && return 0
|
||||
_COMMON_LOADED=1
|
||||
|
||||
# ── 根目录(workspace46/)──────────────────────────────────────────────────────
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
# ── 运行时目录(测试服务器环境) ───────────────────────────────────────────────
|
||||
LOG_DIR="$ROOT_DIR/.deploy-test/logs" # 后端服务日志
|
||||
PID_DIR="$ROOT_DIR/.deploy-test/pids" # PID 文件(含日志收集进程)
|
||||
BUILD_DIR="$ROOT_DIR/.deploy-test/bin" # 编译产物
|
||||
DATA_DIR="$ROOT_DIR/.deploy-test/docker-data" # Docker 数据卷
|
||||
DOCKER_LOG_DIR="$ROOT_DIR/.deploy-test/docker-logs" # Docker 容器日志
|
||||
SCRIPT_LOG_DIR="$ROOT_DIR/.deploy-test/script-logs" # 脚本执行日志
|
||||
ENV_FILE="$ROOT_DIR/.env.deploy-test"
|
||||
|
||||
# ── 颜色 ───────────────────────────────────────────────────────────────────────
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
|
||||
|
||||
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
|
||||
success() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||
step() { echo -e "\n${BOLD}${BLUE}▶ $*${NC}"; }
|
||||
header() {
|
||||
echo ""
|
||||
echo -e "${BOLD}${BLUE}══════════════════════════════════════════${NC}"
|
||||
echo -e "${BOLD}${BLUE} $*${NC}"
|
||||
echo -e "${BOLD}${BLUE}══════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
# ── 初始化运行时目录 ────────────────────────────────────────────────────────────
|
||||
init_dirs() {
|
||||
mkdir -p "$LOG_DIR" "$PID_DIR" "$BUILD_DIR" "$DATA_DIR" \
|
||||
"$DOCKER_LOG_DIR" "$SCRIPT_LOG_DIR"
|
||||
}
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# 脚本执行日志
|
||||
# 调用位置:每个脚本 init_dirs 之后
|
||||
# 效果:所有输出(stdout+stderr)同时写入 .local-dev/script-logs/<name>-<ts>.log
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
init_script_log() {
|
||||
local script_name
|
||||
script_name="$(basename "${BASH_SOURCE[1]:-$0}" .sh)"
|
||||
local ts; ts="$(date +%Y%m%d-%H%M%S)"
|
||||
export _CURRENT_SCRIPT_LOG="$SCRIPT_LOG_DIR/${script_name}-${ts}.log"
|
||||
mkdir -p "$SCRIPT_LOG_DIR"
|
||||
|
||||
# 写入文件头(纯文本,不含颜色码)
|
||||
{
|
||||
echo "========================================"
|
||||
echo "Script : $script_name"
|
||||
echo "Started: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo "========================================"
|
||||
} > "$_CURRENT_SCRIPT_LOG"
|
||||
|
||||
# exec:将所有后续输出同时流向终端和日志文件
|
||||
# 用 sed 去除 ANSI 颜色码,保证日志文件可读
|
||||
exec > >(tee >(sed $'s/\033\\[[0-9;]*m//g' >> "$_CURRENT_SCRIPT_LOG")) 2>&1
|
||||
|
||||
info "脚本日志 → $_CURRENT_SCRIPT_LOG"
|
||||
}
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Docker 容器日志收集
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
# 启动后台日志收集进程:docker logs -f → 本地文件(按日期滚动)
|
||||
start_docker_logger() {
|
||||
local cname="$1"
|
||||
local svc="${cname#dev-}" # dev-redis → redis
|
||||
local log_dir="$DOCKER_LOG_DIR/$svc"
|
||||
local logfile="$log_dir/${svc}-$(date +%Y%m%d).log"
|
||||
local pid_file="$PID_DIR/docker-log-${cname}.pid"
|
||||
|
||||
mkdir -p "$log_dir"
|
||||
|
||||
# 停止已有的收集进程
|
||||
if [[ -f "$pid_file" ]] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then
|
||||
kill "$(cat "$pid_file")" 2>/dev/null || true
|
||||
sleep 0.3
|
||||
fi
|
||||
|
||||
# 写分隔符,区分每次启动会话
|
||||
{
|
||||
echo ""
|
||||
echo "──── 容器启动 $(date '+%Y-%m-%d %H:%M:%S') ────"
|
||||
} >> "$logfile"
|
||||
|
||||
# 后台跟踪容器日志(docker logs 本身已含历史,--tail 0 只取新增)
|
||||
# 首次启动时先 dump 当前快照,再 follow 新增
|
||||
docker logs "$cname" >> "$logfile" 2>&1 || true
|
||||
docker logs -f --tail 0 "$cname" >> "$logfile" 2>&1 &
|
||||
echo $! > "$pid_file"
|
||||
|
||||
info " 容器日志 → $logfile"
|
||||
}
|
||||
|
||||
# 停止容器日志收集进程
|
||||
stop_docker_logger() {
|
||||
local cname="$1"
|
||||
local pid_file="$PID_DIR/docker-log-${cname}.pid"
|
||||
if [[ -f "$pid_file" ]]; then
|
||||
local pid; pid=$(cat "$pid_file")
|
||||
kill "$pid" 2>/dev/null || true
|
||||
rm -f "$pid_file"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 加载 .env.local ─────────────────────────────────────────────────────────────
|
||||
load_env() {
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
error ".env.local 不存在,请先执行: ./deploy-test/01-init-env.sh"
|
||||
exit 1
|
||||
fi
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
}
|
||||
|
||||
# ── 检查必要工具 ────────────────────────────────────────────────────────────────
|
||||
require_tools() {
|
||||
local missing=()
|
||||
for tool in "$@"; do
|
||||
command -v "$tool" &>/dev/null || missing+=("$tool")
|
||||
done
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
error "缺少必要工具: ${missing[*]}"
|
||||
for t in "${missing[@]}"; do
|
||||
case "$t" in
|
||||
go) echo " → 安装 Go: https://go.dev/dl/" ;;
|
||||
docker) echo " → 安装 Docker Desktop: https://www.docker.com/products/docker-desktop/" ;;
|
||||
esac
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Docker daemon 检查 ──────────────────────────────────────────────────────────
|
||||
require_docker_running() {
|
||||
require_tools docker
|
||||
if ! docker info &>/dev/null; then
|
||||
error "Docker daemon 未运行,请启动 Docker Desktop"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 启动单个后端服务(nohup 后台) ───────────────────────────────────────────────
|
||||
start_svc() {
|
||||
local name="$1" bin="$2" args="${3:-}" workdir="${4:-$ROOT_DIR}"
|
||||
local pidfile="$PID_DIR/$name.pid" logfile="$LOG_DIR/$name.log"
|
||||
|
||||
if [[ -f "$pidfile" ]] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
|
||||
warn "$name 已在运行 (PID=$(cat "$pidfile")),跳过"
|
||||
return 0
|
||||
fi
|
||||
|
||||
[[ ! -f "$bin" ]] && { error "$name 二进制不存在 ($bin),请先执行 04-build.sh"; return 1; }
|
||||
|
||||
info "启动 $name ..."
|
||||
(
|
||||
cd "$workdir"
|
||||
# shellcheck disable=SC2086
|
||||
nohup "$bin" $args > "$logfile" 2>&1 &
|
||||
echo $! > "$pidfile"
|
||||
)
|
||||
sleep 1
|
||||
if kill -0 "$(cat "$pidfile")" 2>/dev/null; then
|
||||
success " $name 已启动 (PID=$(cat "$pidfile")) → $logfile"
|
||||
else
|
||||
error " $name 启动失败,查看日志:"
|
||||
tail -20 "$logfile" 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 停止单个后端服务 ────────────────────────────────────────────────────────────
|
||||
stop_svc() {
|
||||
local name="$1" pidfile="$PID_DIR/$name.pid"
|
||||
if [[ -f "$pidfile" ]]; then
|
||||
local pid; pid=$(cat "$pidfile")
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill "$pid" && success "$name 已停止 (PID=$pid)"
|
||||
else
|
||||
warn "$name 进程 $pid 不存在(可能已退出)"
|
||||
fi
|
||||
rm -f "$pidfile"
|
||||
else
|
||||
warn "$name 没有 PID 记录(未运行)"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Docker 容器状态打印 ─────────────────────────────────────────────────────────
|
||||
print_container_status() {
|
||||
local label="$1" cname="$2" port="$3"
|
||||
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${cname}$"; then
|
||||
printf " ${GREEN}●${NC} %-12s container=%-14s :%-5s\n" "$label" "$cname" "$port"
|
||||
elif docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^${cname}$"; then
|
||||
printf " ${YELLOW}○${NC} %-12s stopped=%-14s :%-5s\n" "$label" "$cname" "$port"
|
||||
else
|
||||
printf " ${RED}✗${NC} %-12s (未创建) :%-5s\n" "$label" "$port"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 后端服务状态打印 ────────────────────────────────────────────────────────────
|
||||
print_svc_status() {
|
||||
local name="$1" desc="$2" pidfile="$PID_DIR/$name.pid"
|
||||
if [[ -f "$pidfile" ]] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
|
||||
printf " ${GREEN}●${NC} %-18s PID=%-7s %s\n" "$name" "$(cat "$pidfile")" "$desc"
|
||||
else
|
||||
printf " ${RED}○${NC} %-18s %-11s %s\n" "$name" "未运行" "$desc"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 所有后端服务名列表 ──────────────────────────────────────────────────────────
|
||||
ALL_SVCS=(openim-server chat-rpc admin-rpc chat-api admin-api meetingmsg livecloud livestream build-server)
|
||||
Reference in New Issue
Block a user