File size: 5,084 Bytes
5bfb40b
 
d85e519
5bfb40b
d85e519
5bfb40b
 
d85e519
8783c2d
 
 
5bfb40b
8783c2d
 
 
d85e519
8783c2d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5bfb40b
 
d85e519
5bfb40b
 
 
 
d85e519
5bfb40b
 
 
8783c2d
 
 
 
 
 
 
5bfb40b
d85e519
8783c2d
 
 
 
 
 
 
d85e519
5bfb40b
 
 
d85e519
8783c2d
5bfb40b
 
 
 
 
 
d85e519
 
5bfb40b
 
d85e519
 
5bfb40b
 
 
 
69b897d
5bfb40b
 
 
 
8783c2d
 
 
 
5bfb40b
8783c2d
 
 
 
 
5bfb40b
 
8783c2d
5bfb40b
 
8783c2d
 
 
5bfb40b
 
 
 
0b18167
8783c2d
 
 
5bfb40b
 
 
 
 
753e568
8783c2d
 
 
 
5bfb40b
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/bin/sh
# shellcheck shell=sh

set -e

TS() { date "+%Y-%m-%d %H:%M:%S"; }
log() { echo "[$(TS)] [entrypoint] $*"; }

# -----------------------------------------------------------------------------
# 基础目录
# -----------------------------------------------------------------------------
mkdir -p /app/logs /app/data /app/temp
# Redis 数据目录放在 /app/data/redis,这样能随备份一起保存/恢复
REDIS_DIR="${REDIS_DIR:-/app/data/redis}"
mkdir -p "${REDIS_DIR}"

# -----------------------------------------------------------------------------
# 导出备份相关环境变量(给子进程可见)
# -----------------------------------------------------------------------------
export HF_TOKEN="${HF_TOKEN:-}"
export DATASET_ID="${DATASET_ID:-}"
export SYNC_INTERVAL MAX_BACKUPS BACKUP_PREFIX BACKUP_PATHS BACKUP_EXCLUDE

# 若未指定,给出对持久化友好的默认值(相对路径,配合 tar -C /)
BACKUP_PATHS="${BACKUP_PATHS:-app/data,app/data/redis}"
BACKUP_EXCLUDE="${BACKUP_EXCLUDE:-*.tmp,*.cache,**/.DS_Store}"
export BACKUP_PATHS BACKUP_EXCLUDE

# -----------------------------------------------------------------------------
# 在任何服务启动前先尝试恢复数据(包含 Redis 的 RDB/AOF)
# -----------------------------------------------------------------------------
if [ -n "$HF_TOKEN" ] && [ -n "$DATASET_ID" ]; then
  /app/tools/hf-backup.sh restore || log "Restore skipped/failed, continue."
else
  log "未配置 HF_TOKEN/DATASET_ID,跳过恢复。"
fi

# -----------------------------------------------------------------------------
# 启动(内置或外置)Redis
# -----------------------------------------------------------------------------
REDIS_HOST="${REDIS_HOST:-127.0.0.1}"
REDIS_PORT="${REDIS_PORT:-6379}"

start_internal_redis="false"
case "$REDIS_HOST" in
  ""|"127.0.0.1"|"localhost") start_internal_redis="true" ;;
esac

if [ "$start_internal_redis" = "true" ]; then
  log "Starting embedded Redis on 127.0.0.1:${REDIS_PORT} ..."
  if [ -n "${REDIS_PASSWORD:-}" ]; then
    redis-server \
      --port "${REDIS_PORT}" --bind 127.0.0.1 \
      --dir "${REDIS_DIR}" \
      --dbfilename dump.rdb \
      --appendonly yes --appendfilename appendonly.aof \
      --appendfsync everysec \
      --save 60 1 \
      --requirepass "${REDIS_PASSWORD}" &
  else
    redis-server \
      --port "${REDIS_PORT}" --bind 127.0.0.1 \
      --dir "${REDIS_DIR}" \
      --dbfilename dump.rdb \
      --appendonly yes --appendfilename appendonly.aof \
      --appendfsync everysec \
      --save 60 1 &
  fi
else
  log "Using EXTERNAL Redis at ${REDIS_HOST}:${REDIS_PORT}, skip embedded Redis."
fi

# 等待 Redis 就绪
log "Waiting for Redis on ${REDIS_HOST}:${REDIS_PORT} ..."
i=0
while :; do
  if [ -n "${REDIS_PASSWORD:-}" ]; then
    if redis-cli -h "${REDIS_HOST}" -p "${REDIS_PORT}" -a "${REDIS_PASSWORD}" ping >/dev/null 2>&1; then
      break
    fi
  else
    if redis-cli -h "${REDIS_HOST}" -p "${REDIS_PORT}" ping >/dev/null 2>&1; then
      break
    fi
  fi
  i=$((i+1))
  if [ "$i" -ge 60 ]; then
    log "Redis not ready after 60s, exit."
    exit 1
  fi
  sleep 1
done
log "Redis is ready."

# -----------------------------------------------------------------------------
# 备份守护进程(可选:开机先做一份一次性备份)
# BACKUP_ON_START=true 时,先执行一次上传,随后开启守护
# -----------------------------------------------------------------------------
if [ -n "$HF_TOKEN" ] && [ -n "$DATASET_ID" ]; then
  if [ "${BACKUP_ON_START:-false}" = "true" ]; then
    /app/tools/hf-backup.sh once || log "First backup failed (ignored)."
  fi
  # 同时输出到控制台和日志文件,便于在 HF 控制台直接看到
  /app/tools/hf-backup.sh daemon 2>&1 | tee -a /app/logs/hf-backup.log &
  log "启动 HF Dataset 备份服务(间隔 ${SYNC_INTERVAL:-3600}s,保留 ${MAX_BACKUPS:-10} 份)"
else
  log "未配置 HF_TOKEN/DATASET_ID,跳过备份守护进程。"
fi

# -----------------------------------------------------------------------------
# 可选:强制重置管理员(会删除 init.json)
# -----------------------------------------------------------------------------
if [ "${FORCE_ADMIN_RESET:-false}" = "true" ]; then
  log "FORCE_ADMIN_RESET=true, remove /app/data/init.json"
  rm -f /app/data/init.json
fi

# -----------------------------------------------------------------------------
# 初始化管理员 / 应用准备
# -----------------------------------------------------------------------------
if [ -n "${ADMIN_USERNAME:-}" ] && [ -n "${ADMIN_PASSWORD:-}" ]; then
  log "Bootstrapping admin user: ${ADMIN_USERNAME}"
else
  log "ADMIN_USERNAME/ADMIN_PASSWORD 未设置,将按已有 init.json 或默认逻辑处理。"
fi
npm run setup

# -----------------------------------------------------------------------------
# 启动应用
# -----------------------------------------------------------------------------
HOST="${HOST:-0.0.0.0}"
PORT="${PORT:-7860}"
log "Starting app on ${HOST}:${PORT} ..."
exec node src/app.js