162 lines
5.4 KiB
Bash
162 lines
5.4 KiB
Bash
#!/bin/sh
|
||
# =============================================================================
|
||
# 追光AI CRON 容器启动入口
|
||
# - 用 supercronic 调度 /app/crontab.txt 里的任务
|
||
# - 跟 host cron 行为一致,但完全在容器内
|
||
# - 增强:信号处理、错误处理、日志轮转集成
|
||
# =============================================================================
|
||
set -e
|
||
|
||
cd /app
|
||
|
||
# =============================================================================
|
||
# 信号处理 - 优雅关闭
|
||
# =============================================================================
|
||
SUPERCRONIC_PID=""
|
||
|
||
cleanup() {
|
||
echo "[entrypoint-cron] Received shutdown signal, stopping gracefully..."
|
||
if [ -n "$SUPERCRONIC_PID" ]; then
|
||
kill -TERM "$SUPERCRONIC_PID" 2>/dev/null || true
|
||
# 等待进程结束,最多 30 秒
|
||
for i in $(seq 1 30); do
|
||
if ! kill -0 "$SUPERCRONIC_PID" 2>/dev/null; then
|
||
echo "[entrypoint-cron] Process exited cleanly"
|
||
break
|
||
fi
|
||
sleep 1
|
||
done
|
||
# 如果还没退出,强制终止
|
||
if kill -0 "$SUPERCRONIC_PID" 2>/dev/null; then
|
||
echo "[entrypoint-cron] Force killing process..."
|
||
kill -9 "$SUPERCRONIC_PID" 2>/dev/null || true
|
||
fi
|
||
fi
|
||
exit 0
|
||
}
|
||
|
||
trap cleanup TERM INT QUIT
|
||
|
||
# =============================================================================
|
||
# 日志轮转配置(通过环境变量控制)
|
||
# =============================================================================
|
||
# LOG_MAX_SIZE: 单个日志文件最大大小(默认 100M)
|
||
# LOG_MAX_FILES: 保留的历史日志文件数(默认 7)
|
||
# LOG_COMPRESS: 是否压缩历史日志(默认 true)
|
||
LOG_MAX_SIZE="${LOG_MAX_SIZE:-100M}"
|
||
LOG_MAX_FILES="${LOG_MAX_FILES:-7}"
|
||
LOG_COMPRESS="${LOG_COMPRESS:-true}"
|
||
|
||
# 如果启用了日志文件输出,配置 logrotate
|
||
if [ -n "$LOG_FILE" ]; then
|
||
echo "[entrypoint-cron] Log file configured: $LOG_FILE"
|
||
echo "[entrypoint-cron] Log rotation: max_size=$LOG_MAX_SIZE, max_files=$LOG_MAX_FILES, compress=$LOG_COMPRESS"
|
||
|
||
# 创建 logrotate 配置
|
||
cat > /etc/logrotate.d/zhuiguang-cron <<EOF
|
||
$LOG_FILE {
|
||
size $LOG_MAX_SIZE
|
||
rotate $LOG_MAX_FILES
|
||
compress
|
||
delaycompress
|
||
missingok
|
||
notifempty
|
||
create 0644 root root
|
||
postrotate
|
||
# 通知 supercronic 重新打开日志文件(如果支持)
|
||
true
|
||
endscript
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Seed data volume if empty
|
||
# =============================================================================
|
||
if [ ! -f /app/data/bot-characters.json ] && [ -d /app/data-seed ]; then
|
||
echo "[entrypoint] Seeding data volume..."
|
||
cp -r /app/data-seed/* /app/data/
|
||
fi
|
||
|
||
# =============================================================================
|
||
# .env 校验
|
||
# =============================================================================
|
||
if [ ! -f /app/.env ]; then
|
||
echo "[entrypoint-cron] FATAL: /app/.env not found. Mount .env file into container."
|
||
exit 1
|
||
fi
|
||
|
||
# =============================================================================
|
||
# crontab 文件校验
|
||
# =============================================================================
|
||
if [ ! -f /app/crontab.txt ]; then
|
||
echo "[entrypoint-cron] FATAL: /app/crontab.txt not found. Mount crontab into container."
|
||
exit 1
|
||
fi
|
||
|
||
# =============================================================================
|
||
# 健康检查端点(可选)
|
||
# =============================================================================
|
||
if [ "$HEALTH_CHECK_ENABLED" = "true" ]; then
|
||
HEALTH_PORT="${HEALTH_CHECK_PORT:-8311}"
|
||
echo "[entrypoint-cron] Health check enabled on port $HEALTH_PORT"
|
||
|
||
# 启动简单的健康检查 HTTP 服务器
|
||
(
|
||
while true; do
|
||
echo -e "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nOK" | nc -l -p "$HEALTH_PORT" -q 1 2>/dev/null || true
|
||
done
|
||
) &
|
||
HEALTH_PID=$!
|
||
echo "[entrypoint-cron] Health check server started (PID: $HEALTH_PID)"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# supercronic 启动
|
||
# =============================================================================
|
||
echo "[entrypoint-cron] Starting supercronic..."
|
||
echo "[entrypoint-cron] crontab:"
|
||
sed 's/^/ /' /app/crontab.txt
|
||
|
||
# 构建启动参数
|
||
SUPERCRONIC_ARGS=""
|
||
|
||
# Prometheus 监控(可选)
|
||
if [ "$PROMETHEUS_ENABLED" != "false" ]; then
|
||
PROMETHEUS_PORT="${PROMETHEUS_PORT:-8310}"
|
||
SUPERCRONIC_ARGS="$SUPERCRONIC_ARGS -prometheus-listen-address 0.0.0.0:$PROMETHEUS_PORT"
|
||
echo "[entrypoint-cron] Prometheus metrics enabled on port $PROMETHEUS_PORT"
|
||
fi
|
||
|
||
# 日志分离(可选)
|
||
if [ "$SPLIT_LOGS" = "true" ]; then
|
||
SUPERCRONIC_ARGS="$SUPERCRONIC_ARGS -split-logs"
|
||
echo "[entrypoint-cron] Split logs enabled (stdout/stderr separated)"
|
||
fi
|
||
|
||
# 调试模式
|
||
if [ "$DEBUG" = "true" ]; then
|
||
SUPERCRONIC_ARGS="$SUPERCRONIC_ARGS -debug"
|
||
echo "[entrypoint-cron] Debug mode enabled"
|
||
fi
|
||
|
||
# 启动 supercronic(后台运行以捕获 PID)
|
||
/usr/local/bin/supercronic-linux-amd64 $SUPERCRONIC_ARGS /app/crontab.txt &
|
||
SUPERCRONIC_PID=$!
|
||
|
||
echo "[entrypoint-cron] Supercronic started with PID: $SUPERCRONIC_PID"
|
||
echo "[entrypoint-cron] Container ready"
|
||
|
||
# 等待 supercronic 进程(同时保持信号处理能力)
|
||
wait "$SUPERCRONIC_PID"
|
||
EXIT_CODE=$?
|
||
|
||
echo "[entrypoint-cron] Supercronic exited with code: $EXIT_CODE"
|
||
|
||
# 清理健康检查服务器
|
||
if [ -n "$HEALTH_PID" ]; then
|
||
kill "$HEALTH_PID" 2>/dev/null || true
|
||
fi
|
||
|
||
exit $EXIT_CODE
|