173 lines
4.5 KiB
Bash
Executable File
173 lines
4.5 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# 定义常量
|
||
PORT=8888
|
||
LOG_FILE="logs/$(date +%Y%m%d_%H%M%S)_message.log"
|
||
PID_FILE="logs/app.pid"
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
#
|
||
# 创建日志目录
|
||
mkdir -p "$SCRIPT_DIR/logs"
|
||
|
||
# 切换到脚本目录
|
||
cd "$SCRIPT_DIR" || {
|
||
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] 错误: 无法进入目录 $SCRIPT_DIR" | tee -a "$LOG_FILE"
|
||
exit 1
|
||
}
|
||
|
||
# 日志输出函数
|
||
log_info() {
|
||
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] [INFO] $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_error() {
|
||
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] [ERROR] $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_warn() {
|
||
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] [WARN] $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
# 检查端口是否被占用
|
||
check_port() {
|
||
local port=$1
|
||
if command -v lsof >/dev/null 2>&1; then
|
||
lsof -i :$port >/dev/null 2>&1
|
||
elif command -v netstat >/dev/null 2>&1; then
|
||
netstat -tuln | grep ":$port " >/dev/null 2>&1
|
||
elif command -v ss >/dev/null 2>&1; then
|
||
ss -tuln | grep ":$port " >/dev/null 2>&1
|
||
else
|
||
log_error "无法找到检查端口的命令 (lsof, netstat, ss)"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 健康检查函数
|
||
health_check() {
|
||
local url="http://localhost:$PORT"
|
||
local timeout=5
|
||
|
||
if command -v curl >/dev/null 2>&1; then
|
||
curl -s --connect-timeout $timeout --max-time $timeout "$url" >/dev/null 2>&1
|
||
elif command -v wget >/dev/null 2>&1; then
|
||
wget -q --timeout=$timeout --tries=1 -O /dev/null "$url" >/dev/null 2>&1
|
||
else
|
||
log_warn "无法找到HTTP检查工具 (curl, wget),跳过健康检查"
|
||
return 0
|
||
fi
|
||
}
|
||
|
||
# 停止现有进程
|
||
stop_existing_process() {
|
||
log_info "停止现有进程..."
|
||
|
||
# 从PID文件停止
|
||
if [ -f "$PID_FILE" ]; then
|
||
local pid=$(cat "$PID_FILE")
|
||
if kill -0 "$pid" 2>/dev/null; then
|
||
log_info "正在停止进程 PID: $pid"
|
||
kill "$pid"
|
||
sleep 2
|
||
if kill -0 "$pid" 2>/dev/null; then
|
||
log_warn "进程仍在运行,强制终止"
|
||
kill -9 "$pid"
|
||
fi
|
||
rm -f "$PID_FILE"
|
||
else
|
||
log_info "PID文件中的进程已不存在,清理PID文件"
|
||
rm -f "$PID_FILE"
|
||
fi
|
||
fi
|
||
|
||
# 通过端口查找并停止进程
|
||
if check_port $PORT; then
|
||
log_info "发现端口 $PORT 仍被占用,查找并停止相关进程"
|
||
if command -v lsof >/dev/null 2>&1; then
|
||
local pids=$(lsof -ti :$PORT)
|
||
if [ -n "$pids" ]; then
|
||
echo "$pids" | xargs kill -15 2>/dev/null || true
|
||
sleep 2
|
||
# 如果进程仍在运行,强制杀死
|
||
local remaining_pids=$(lsof -ti :$PORT 2>/dev/null)
|
||
if [ -n "$remaining_pids" ]; then
|
||
echo "$remaining_pids" | xargs kill -9 2>/dev/null || true
|
||
fi
|
||
fi
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# 启动应用
|
||
start_app() {
|
||
log_info "开始启动应用..."
|
||
|
||
# 后台运行Python程序
|
||
nohup python main.py >> "$LOG_FILE" 2>&1 &
|
||
local app_pid=$!
|
||
|
||
# 保存PID
|
||
echo $app_pid > "$PID_FILE"
|
||
log_info "应用已启动,PID: $app_pid"
|
||
|
||
# 等待应用启动
|
||
local max_wait=30
|
||
local wait_time=0
|
||
|
||
while [ $wait_time -lt $max_wait ]; do
|
||
if check_port $PORT; then
|
||
log_info "端口 $PORT 已开始监听"
|
||
break
|
||
fi
|
||
sleep 1
|
||
wait_time=$((wait_time + 1))
|
||
done
|
||
|
||
if [ $wait_time -ge $max_wait ]; then
|
||
log_error "应用启动超时,端口 $PORT 未开始监听"
|
||
return 1
|
||
fi
|
||
|
||
# 健康检查
|
||
sleep 2
|
||
if health_check; then
|
||
log_info "应用健康检查通过"
|
||
return 0
|
||
else
|
||
log_warn "应用健康检查失败,但端口已监听"
|
||
return 0
|
||
fi
|
||
}
|
||
|
||
# 主逻辑
|
||
main() {
|
||
log_info "开始检查应用状态..."
|
||
|
||
# 检查端口是否被占用
|
||
if check_port $PORT; then
|
||
log_info "检测到端口 $PORT 已被占用"
|
||
|
||
# 进行健康检查
|
||
if health_check; then
|
||
log_info "应用正常运行,端口 $PORT 可正常访问,跳过重启"
|
||
exit 0
|
||
else
|
||
log_warn "端口 $PORT 被占用但健康检查失败,准备重启应用"
|
||
stop_existing_process
|
||
fi
|
||
else
|
||
log_info "端口 $PORT 未被占用,准备启动应用"
|
||
fi
|
||
|
||
# 启动应用
|
||
if start_app; then
|
||
log_info "应用启动成功"
|
||
else
|
||
log_error "应用启动失败"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 执行主函数
|
||
main
|