xinli/start.sh

124 lines
3.8 KiB
Bash
Raw Permalink Normal View History

2026-02-24 16:49:05 +08:00
#!/usr/bin/env bash
set -euo pipefail
# ====== 可改配置 ======
APP_NAME="xinli-server"
PORT="30081"
JAR_NAME="ry-xinli-admin.jar" # 改成你的实际jar文件名
APP_HOME="$(cd "$(dirname "$0")" && pwd)"
JAR_PATH="${APP_HOME}/${JAR_NAME}"
LOG_DIR="${APP_HOME}/logs"
LOG_FILE="${LOG_DIR}/${APP_NAME}.log"
PID_FILE="${APP_HOME}/${APP_NAME}.pid"
JAVA_OPTS="-Xms512m -Xmx1024m -Dfile.encoding=UTF-8"
SPRING_OPTS="--server.port=${PORT} --server.address=0.0.0.0"
# 如果你走 Python RAG可选
export RAG_PYTHON_URL="${RAG_PYTHON_URL:-http://127.0.0.1:5000}"
# ======================
mkdir -p "${LOG_DIR}"
echo "[1/4] 检查 jar 是否存在:${JAR_PATH}"
if [[ ! -f "${JAR_PATH}" ]]; then
echo "ERROR: jar 不存在:${JAR_PATH}"
exit 1
fi
kill_by_port() {
local port="$1"
local pids=""
# 优先用 lsof
if command -v lsof >/dev/null 2>&1; then
pids="$(lsof -ti tcp:${port} 2>/dev/null || true)"
# 再用 ss大多数 Linux 有)
elif command -v ss >/dev/null 2>&1; then
# 从 ss 输出里提取 pid=xxxx
pids="$(ss -lntp 2>/dev/null | awk -v p=":${port}" '$4 ~ p {print $0}' | sed -n 's/.*pid=\\([0-9]\\+\\).*/\\1/p' | sort -u)"
# 再用 netstat老系统
elif command -v netstat >/dev/null 2>&1; then
pids="$(netstat -lntp 2>/dev/null | awk -v p=":${port}" '$4 ~ p {print $7}' | cut -d/ -f1 | grep -E '^[0-9]+$' | sort -u)"
else
echo "ERROR: 找不到 lsof/ss/netstat无法通过端口查进程。请先安装 lsof推荐。"
exit 1
fi
if [[ -n "${pids}" ]]; then
echo "[2/4] 端口 ${port} 被占用,准备杀进程:${pids}"
for pid in ${pids}; do
echo " - kill ${pid}"
kill "${pid}" 2>/dev/null || true
done
# 等待退出,最多 10 秒
for _ in {1..10}; do
sleep 1
local still=""
if command -v lsof >/dev/null 2>&1; then
still="$(lsof -ti tcp:${port} 2>/dev/null || true)"
elif command -v ss >/dev/null 2>&1; then
still="$(ss -lntp 2>/dev/null | awk -v p=":${port}" '$4 ~ p {print $0}' | sed -n 's/.*pid=\\([0-9]\\+\\).*/\\1/p' | sort -u)"
elif command -v netstat >/dev/null 2>&1; then
still="$(netstat -lntp 2>/dev/null | awk -v p=":${port}" '$4 ~ p {print $7}' | cut -d/ -f1 | grep -E '^[0-9]+$' | sort -u)"
fi
[[ -z "${still}" ]] && break
done
# 如果还占用就强杀
if command -v lsof >/dev/null 2>&1; then
pids="$(lsof -ti tcp:${port} 2>/dev/null || true)"
fi
if [[ -n "${pids}" ]]; then
echo "端口仍被占用,强制 kill -9${pids}"
for pid in ${pids}; do
kill -9 "${pid}" 2>/dev/null || true
done
fi
else
echo "[2/4] 端口 ${port} 未占用"
fi
}
stop_by_pidfile() {
if [[ -f "${PID_FILE}" ]]; then
local pid
pid="$(cat "${PID_FILE}" || true)"
if [[ -n "${pid}" ]] && kill -0 "${pid}" >/dev/null 2>&1; then
echo "[2/4] 发现旧 PID_FILE${PID_FILE} (pid=${pid}),先停止旧进程"
kill "${pid}" 2>/dev/null || true
sleep 2
kill -9 "${pid}" 2>/dev/null || true
fi
rm -f "${PID_FILE}" >/dev/null 2>&1 || true
fi
}
echo "[2/4] 停止旧进程(先按 PID_FILE再按端口"
stop_by_pidfile
kill_by_port "${PORT}"
echo "[3/4] 启动应用(日志:${LOG_FILE}"
nohup java ${JAVA_OPTS} -jar "${JAR_PATH}" ${SPRING_OPTS} >> "${LOG_FILE}" 2>&1 &
echo $! > "${PID_FILE}"
echo "已启动pid=$(cat "${PID_FILE}")"
echo "[4/4] 等待端口 ${PORT} 监听(最多 30 秒)"
for i in {1..30}; do
if command -v ss >/dev/null 2>&1; then
if ss -lnt | awk '{print $4}' | grep -q ":${PORT}\$"; then
echo "OK端口已监听。"
echo "查看日志tail -f ${LOG_FILE}"
exit 0
fi
else
# 没有 ss 就不硬等,提示用户看日志
break
fi
sleep 1
done
echo "WARN30 秒内未检测到端口监听,请查看日志排查:${LOG_FILE}"
exit 1