Some checks failed
Mark & close stale issues / stale (push) Has been cancelled
Vulnerability Scan / trivy-scan (1.0) (push) Has been cancelled
Vulnerability Scan / trivy-scan (master) (push) Has been cancelled
CodeQL Advanced / Analyze (java-kotlin) (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
408 lines
18 KiB
Bash
Executable File
408 lines
18 KiB
Bash
Executable File
#!/bin/bash
|
||
# ═══════════════════════════════════════════════════════════════════════════════
|
||
# Hawkbit Monolith + UI 本地启动脚本(替代 docker-compose)
|
||
# ═══════════════════════════════════════════════════════════════════════════════
|
||
#
|
||
# 两种模式:
|
||
# h2 H2 内嵌数据库(零依赖,开发测试用)
|
||
# postgres PostgreSQL + RabbitMQ(模拟生产环境)
|
||
#
|
||
# 用法:
|
||
# ./start-hawkbit.sh h2 # H2 模式,端口 9090/9091
|
||
# ./start-hawkbit.sh postgres # PostgreSQL 模式,端口 9090/9091
|
||
# ./start-hawkbit.sh stop # 停止所有
|
||
# ./start-hawkbit.sh status # 查看状态
|
||
# ./start-hawkbit.sh dbinit # 仅执行数据库初始化(postgres 模式)
|
||
# ./start-hawkbit.sh help # 帮助
|
||
#
|
||
# 对应 docker-compose 文件:
|
||
# h2 → docker-compose-monolith-with-ui-postgres.yml (但用 H2)
|
||
# postgres → docker-compose-monolith-dbinit-with-ui-postgres.yml
|
||
# ═══════════════════════════════════════════════════════════════════════════════
|
||
|
||
set -e
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
HAWKBIT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
LOG_DIR="$SCRIPT_DIR/logs"
|
||
PID_DIR="$SCRIPT_DIR/pid"
|
||
|
||
# ── 配置 ─────────────────────────────────────────────────────────────────────
|
||
MONOLITH_JAR="$HAWKBIT_ROOT/hawkbit-monolith/hawkbit-update-server/target/hawkbit-update-server-0-SNAPSHOT.jar"
|
||
UI_JAR="$HAWKBIT_ROOT/hawkbit-ui/target/hawkbit-ui.jar"
|
||
DBINIT_JAR="$HOME/.m2/repository/org/eclipse/hawkbit/hawkbit-repository-jpa-init/0-SNAPSHOT/hawkbit-repository-jpa-init-0-SNAPSHOT.jar"
|
||
|
||
# 端口
|
||
MONOLITH_PORT=9090
|
||
UI_PORT=9091
|
||
|
||
# PostgreSQL 配置(postgres 模式)
|
||
PG_HOST=localhost
|
||
PG_PORT=5432
|
||
PG_DB=hawkbit
|
||
PG_USER=postgres
|
||
PG_PASSWORD=hawkbit
|
||
|
||
# RabbitMQ 配置(postgres 模式)
|
||
RABBIT_HOST=localhost
|
||
RABBIT_PORT=5672
|
||
|
||
# H2 配置
|
||
H2_DB_DIR="$SCRIPT_DIR/h2data"
|
||
|
||
# JVM 参数
|
||
MONOLITH_XMS=512m
|
||
MONOLITH_XMX=1024m
|
||
UI_XMS=256m
|
||
UI_XMX=512m
|
||
|
||
# ── 颜色 ─────────────────────────────────────────────────────────────────────
|
||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||
error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
||
step() { echo -e "\n${BLUE}═══ $* ═══${NC}"; }
|
||
|
||
# ── 初始化 ───────────────────────────────────────────────────────────────────
|
||
init() {
|
||
mkdir -p "$LOG_DIR" "$PID_DIR"
|
||
}
|
||
|
||
# ── 清理 ─────────────────────────────────────────────────────────────────────
|
||
cleanup_pid() {
|
||
local pid_file="$1"
|
||
local name="$2"
|
||
if [ -f "$pid_file" ]; then
|
||
local pid=$(cat "$pid_file")
|
||
if kill -0 "$pid" 2>/dev/null; then
|
||
info "停止 $name (PID: $pid)"
|
||
kill "$pid" 2>/dev/null || true
|
||
sleep 2
|
||
kill -9 "$pid" 2>/dev/null || true
|
||
fi
|
||
rm -f "$pid_file"
|
||
fi
|
||
}
|
||
|
||
# ── 停止 ─────────────────────────────────────────────────────────────────────
|
||
do_stop() {
|
||
step "停止 Hawkbit 服务"
|
||
|
||
cleanup_pid "$PID_DIR/hawkbit-monolith.pid" "hawkbit-monolith"
|
||
cleanup_pid "$PID_DIR/hawkbit-ui.pid" "hawkbit-ui"
|
||
|
||
if [ -f "$PID_DIR/postgres.pid" ]; then
|
||
local pg_pid=$(cat "$PID_DIR/postgres.pid")
|
||
if kill -0 "$pg_pid" 2>/dev/null; then
|
||
info "停止 PostgreSQL (PID: $pg_pid)"
|
||
pg_ctl -D "$SCRIPT_DIR/pgdata" stop 2>/dev/null || kill "$pg_pid"
|
||
fi
|
||
rm -f "$PID_DIR/postgres.pid"
|
||
fi
|
||
|
||
if [ -f "$PID_DIR/rabbitmq.pid" ]; then
|
||
local rb_pid=$(cat "$PID_DIR/rabbitmq.pid")
|
||
if kill -0 "$rb_pid" 2>/dev/null; then
|
||
info "停止 RabbitMQ (PID: $rb_pid)"
|
||
kill "$rb_pid" 2>/dev/null || true
|
||
fi
|
||
rm -f "$PID_DIR/rabbitmq.pid"
|
||
fi
|
||
|
||
info "全部已停止"
|
||
}
|
||
|
||
# ── 状态 ─────────────────────────────────────────────────────────────────────
|
||
do_status() {
|
||
echo "Hawkbit 服务状态:"
|
||
echo "─────────────────"
|
||
|
||
for svc in "hawkbit-monolith:${MONOLITH_PORT}:$PID_DIR/hawkbit-monolith.pid" \
|
||
"hawkbit-ui:${UI_PORT}:$PID_DIR/hawkbit-ui.pid"; do
|
||
IFS=':' read -r name port pid_file <<< "$svc"
|
||
if [ -f "$pid_file" ] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then
|
||
echo -e " ${GREEN}●${NC} $name (port $port, PID $(cat "$pid_file"))"
|
||
else
|
||
echo -e " ${RED}○${NC} $name (port $port)"
|
||
fi
|
||
done
|
||
|
||
echo ""
|
||
if [ -f "$PID_DIR/postgres.pid" ] && kill -0 "$(cat "$PID_DIR/postgres.pid")" 2>/dev/null; then
|
||
echo -e " ${GREEN}●${NC} PostgreSQL (port $PG_PORT)"
|
||
else
|
||
echo -e " ${YELLOW}○${NC} PostgreSQL (not managed by this script)"
|
||
fi
|
||
}
|
||
|
||
# ── 等待端口 ─────────────────────────────────────────────────────────────────
|
||
wait_for_port() {
|
||
local host=$1 port=$2 timeout=${3:-30} label=${4:-"$host:$port"}
|
||
local waited=0
|
||
while ! (echo >"/dev/tcp/$host/$port") 2>/dev/null; do
|
||
sleep 1
|
||
waited=$((waited + 1))
|
||
if [ $waited -ge $timeout ]; then
|
||
error "$label 启动超时(${timeout}s)"
|
||
return 1
|
||
fi
|
||
done
|
||
info "$label 就绪"
|
||
}
|
||
|
||
# ── H2 模式 ──────────────────────────────────────────────────────────────────
|
||
start_h2() {
|
||
step "H2 模式启动"
|
||
|
||
if [ -f "$PID_DIR/hawkbit-monolith.pid" ] && kill -0 "$(cat "$PID_DIR/hawkbit-monolith.pid")" 2>/dev/null; then
|
||
warn "hawkbit-monolith 已在运行"
|
||
else
|
||
mkdir -p "$H2_DB_DIR"
|
||
|
||
info "启动 hawkbit-update-server (H2, 端口 $MONOLITH_PORT)..."
|
||
nohup java \
|
||
-Xms${MONOLITH_XMS} -Xmx${MONOLITH_XMX} \
|
||
-jar "$MONOLITH_JAR" \
|
||
--server.port=$MONOLITH_PORT \
|
||
--hawkbit.dmf.rabbitmq.enabled=false \
|
||
--hawkbit.server.ddi.security.authentication.anonymous.enabled=true \
|
||
--hawkbit.server.ui.demo.user=admin \
|
||
--hawkbit.server.ui.demo.password=admin \
|
||
--spring.datasource.url="jdbc:h2:file:$H2_DB_DIR/hawkbit;DB_CLOSE_DELAY=-1" \
|
||
>> "$LOG_DIR/hawkbit-monolith.log" 2>&1 &
|
||
echo $! > "$PID_DIR/hawkbit-monolith.pid"
|
||
fi
|
||
|
||
start_ui
|
||
}
|
||
|
||
# ── PostgreSQL 模式 ──────────────────────────────────────────────────────────
|
||
start_postgres() {
|
||
step "PostgreSQL 模式启动"
|
||
|
||
# ── 检查 PostgreSQL ────────────────────────────────────────────────
|
||
if ! command -v pg_isready &>/dev/null; then
|
||
error "PostgreSQL 未安装。请先执行: sudo apt install postgresql-16 rabbitmq-server"
|
||
echo ""
|
||
echo "或者用 H2 模式: $0 h2"
|
||
exit 1
|
||
fi
|
||
|
||
# 确保 PostgreSQL 运行
|
||
if ! pg_isready -h $PG_HOST -p $PG_PORT &>/dev/null; then
|
||
info "启动 PostgreSQL..."
|
||
sudo pg_ctlcluster 16 main start 2>/dev/null || \
|
||
sudo service postgresql start 2>/dev/null || {
|
||
error "无法启动 PostgreSQL"
|
||
exit 1
|
||
}
|
||
fi
|
||
info "PostgreSQL 已就绪"
|
||
|
||
# ── 创建数据库和用户 ──────────────────────────────────────────────
|
||
sudo -u postgres psql -tc "SELECT 1 FROM pg_roles WHERE rolname='$PG_USER'" 2>/dev/null | grep -q 1 || {
|
||
info "创建数据库用户 $PG_USER"
|
||
sudo -u postgres psql -c "CREATE USER $PG_USER WITH PASSWORD '$PG_PASSWORD';" 2>/dev/null
|
||
sudo -u postgres psql -c "ALTER USER $PG_USER CREATEDB;" 2>/dev/null
|
||
}
|
||
|
||
sudo -u postgres psql -tc "SELECT 1 FROM pg_database WHERE datname='$PG_DB'" 2>/dev/null | grep -q 1 || {
|
||
info "创建数据库 $PG_DB"
|
||
sudo -u postgres psql -c "CREATE DATABASE $PG_DB OWNER $PG_USER;" 2>/dev/null
|
||
}
|
||
|
||
# ── RabbitMQ ───────────────────────────────────────────────────────
|
||
if ! rabbitmqctl status &>/dev/null 2>&1; then
|
||
info "启动 RabbitMQ..."
|
||
sudo service rabbitmq-server start 2>/dev/null || {
|
||
warn "RabbitMQ 启动失败,禁用 DMF"
|
||
RABBIT_DISABLED=true
|
||
}
|
||
fi
|
||
[ -z "$RABBIT_DISABLED" ] && info "RabbitMQ 已就绪"
|
||
|
||
# ── DB Init (Flyway 迁移) ──────────────────────────────────────────
|
||
if [ -f "$DBINIT_JAR" ]; then
|
||
step "数据库初始化 (Flyway 迁移)"
|
||
info "执行 Hawkbit DB Init..."
|
||
java \
|
||
-Xms256m -Xmx512m \
|
||
-classpath "$DBINIT_JAR" \
|
||
-Dspring.datasource.url="jdbc:postgresql://${PG_HOST}:${PG_PORT}/${PG_DB}" \
|
||
-Dspring.datasource.username="$PG_USER" \
|
||
-Dspring.datasource.password="$PG_PASSWORD" \
|
||
org.eclipse.hawkbit.repository.jpa.init.HawkbitFlywayDbInit \
|
||
migrate 2>&1 | tee "$LOG_DIR/dbinit.log"
|
||
|
||
if [ ${PIPESTATUS[0]} -ne 0 ]; then
|
||
error "DB 初始化失败,查看日志: $LOG_DIR/dbinit.log"
|
||
exit 1
|
||
fi
|
||
info "DB 初始化完成"
|
||
else
|
||
warn "DB Init JAR 未找到: $DBINIT_JAR"
|
||
warn "跳过 DB 初始化,由 Monolith 内嵌 Flyway 执行"
|
||
fi
|
||
|
||
# ── 启动 Monolith ─────────────────────────────────────────────────
|
||
info "启动 hawkbit-update-server (PostgreSQL, 端口 $MONOLITH_PORT)..."
|
||
|
||
local rabbit_args=""
|
||
if [ "$RABBIT_DISABLED" = true ]; then
|
||
rabbit_args="--hawkbit.dmf.rabbitmq.enabled=false"
|
||
else
|
||
rabbit_args="--spring.rabbitmq.host=$RABBIT_HOST"
|
||
fi
|
||
|
||
nohup java \
|
||
-Xms${MONOLITH_XMS} -Xmx${MONOLITH_XMX} \
|
||
-Dspring.profiles.active=postgresql \
|
||
-jar "$MONOLITH_JAR" \
|
||
--server.port=$MONOLITH_PORT \
|
||
--spring.datasource.url="jdbc:postgresql://${PG_HOST}:${PG_PORT}/${PG_DB}" \
|
||
--spring.datasource.username="$PG_USER" \
|
||
--spring.datasource.password="$PG_PASSWORD" \
|
||
$rabbit_args \
|
||
--hawkbit.server.ddi.security.authentication.anonymous.enabled=true \
|
||
--hawkbit.server.ui.demo.user=admin \
|
||
--hawkbit.server.ui.demo.password=admin \
|
||
>> "$LOG_DIR/hawkbit-monolith.log" 2>&1 &
|
||
echo $! > "$PID_DIR/hawkbit-monolith.pid"
|
||
|
||
wait_for_port localhost $MONOLITH_PORT 60 "hawkbit-monolith"
|
||
|
||
start_ui
|
||
}
|
||
|
||
# ── 启动 UI ──────────────────────────────────────────────────────────────────
|
||
start_ui() {
|
||
if [ -f "$PID_DIR/hawkbit-ui.pid" ] && kill -0 "$(cat "$PID_DIR/hawkbit-ui.pid")" 2>/dev/null; then
|
||
warn "hawkbit-ui 已在运行"
|
||
else
|
||
info "启动 hawkbit-ui (端口 $UI_PORT)..."
|
||
nohup java \
|
||
-Xms${UI_XMS} -Xmx${UI_XMX} \
|
||
-jar "$UI_JAR" \
|
||
--server.port=$UI_PORT \
|
||
--hawkbit.server.mgmturl="http://127.0.0.1:${MONOLITH_PORT}" \
|
||
>> "$LOG_DIR/hawkbit-ui.log" 2>&1 &
|
||
echo $! > "$PID_DIR/hawkbit-ui.pid"
|
||
fi
|
||
|
||
wait_for_port localhost $UI_PORT 30 "hawkbit-ui"
|
||
|
||
step "启动完成"
|
||
echo ""
|
||
echo " ┌─────────────────────────────────────────────────────┐"
|
||
echo " │ Hawkbit Management API : http://localhost:${MONOLITH_PORT}/rest/v1 │"
|
||
echo " │ Hawkbit DDI API : http://localhost:${MONOLITH_PORT}/DEFAULT/controller/v1 │"
|
||
echo " │ Hawkbit UI : http://localhost:${UI_PORT} │"
|
||
echo " │ Admin 账号 : admin / admin │"
|
||
echo " ├─────────────────────────────────────────────────────┤"
|
||
echo " │ 日志目录 : $LOG_DIR"
|
||
echo " │ PID 目录 : $PID_DIR"
|
||
echo " │ 停止 : $0 stop"
|
||
echo " │ 状态 : $0 status"
|
||
echo " └─────────────────────────────────────────────────────┘"
|
||
}
|
||
|
||
# ── 仅 DB 初始化 ─────────────────────────────────────────────────────────────
|
||
do_dbinit() {
|
||
step "数据库初始化"
|
||
|
||
if ! pg_isready -h $PG_HOST -p $PG_PORT &>/dev/null; then
|
||
error "PostgreSQL 未运行"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -f "$DBINIT_JAR" ]; then
|
||
error "DB Init JAR 未找到: $DBINIT_JAR"
|
||
exit 1
|
||
fi
|
||
|
||
java \
|
||
-Xms256m -Xmx512m \
|
||
-classpath "$DBINIT_JAR" \
|
||
-Dspring.datasource.url="jdbc:postgresql://${PG_HOST}:${PG_PORT}/${PG_DB}" \
|
||
-Dspring.datasource.username="$PG_USER" \
|
||
-Dspring.datasource.password="$PG_PASSWORD" \
|
||
org.eclipse.hawkbit.repository.jpa.init.HawkbitFlywayDbInit \
|
||
migrate
|
||
|
||
info "DB 初始化完成"
|
||
}
|
||
|
||
# ── 帮助 ─────────────────────────────────────────────────────────────────────
|
||
do_help() {
|
||
cat << 'EOF'
|
||
╔══════════════════════════════════════════════════════════════════╗
|
||
║ Hawkbit Monolith + UI 本地启动脚本 ║
|
||
╚══════════════════════════════════════════════════════════════════╝
|
||
|
||
用法: start-hawkbit.sh <command>
|
||
|
||
命令:
|
||
h2 H2 内嵌数据库模式(零依赖,开发测试推荐)
|
||
postgres PostgreSQL 模式(需先: sudo apt install postgresql-16 rabbitmq-server)
|
||
stop 停止所有服务
|
||
status 查看服务状态
|
||
dbinit 仅执行 DB 初始化(postgres 模式)
|
||
help 显示此帮助
|
||
|
||
示例:
|
||
./start-hawkbit.sh h2 # 快速启动,用 H2 数据库
|
||
./start-hawkbit.sh postgres # 生产模式,用 PostgreSQL
|
||
./start-hawkbit.sh stop # 停止
|
||
./start-hawkbit.sh status # 查看
|
||
|
||
对应 Docker Compose:
|
||
h2 ≈ docker-compose-monolith-with-ui-postgres.yml (但用 H2)
|
||
postgres ≈ docker-compose-monolith-dbinit-with-ui-postgres.yml
|
||
|
||
区别:
|
||
H2 PostgreSQL
|
||
DB 文件存储 独立服务
|
||
安装 零依赖 sudo apt install postgresql-16
|
||
数据路径 h2data/ PostgreSQL pgdata/
|
||
适用场景 开发/测试 生产模拟
|
||
数据持久化 是 是
|
||
|
||
H2 模式启动后:
|
||
MGMT API: http://localhost:9090/rest/v1
|
||
DDI API: http://localhost:9090/DEFAULT/controller/v1
|
||
UI: http://localhost:9091
|
||
Admin: admin / admin
|
||
EOF
|
||
}
|
||
|
||
# ═══════════════════════════════════════════════════════════════════════════════
|
||
# Main
|
||
# ═══════════════════════════════════════════════════════════════════════════════
|
||
init
|
||
|
||
case "${1:-help}" in
|
||
h2)
|
||
start_h2
|
||
;;
|
||
postgres)
|
||
start_postgres
|
||
;;
|
||
stop)
|
||
do_stop
|
||
;;
|
||
status)
|
||
do_status
|
||
;;
|
||
dbinit)
|
||
do_dbinit
|
||
;;
|
||
help|--help|-h)
|
||
do_help
|
||
;;
|
||
*)
|
||
error "未知命令: $1"
|
||
do_help
|
||
exit 1
|
||
;;
|
||
esac
|