fe / scripts /hf-entrypoint.sh
GGSheng's picture
feat: deploy Gemma 4 to hf space
3a5cf48 verified
#!/usr/bin/env bash
# hf-entrypoint.sh - HF Spaces 容器入口
set -euo pipefail
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting..."
# ============================================
# 0. 保存环境变量到 /etc/profile.d,供后续 bash 会话使用
# ============================================
if [[ -x /usr/local/bin/save-env.sh ]]; then
/usr/local/bin/save-env.sh
else
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: warning: save-env.sh not found, skipping env export"
fi
# 加载已保存的环境变量
if [[ -f /etc/profile.d/openclaw-env.sh ]]; then
# shellcheck source=/dev/null
source /etc/profile.d/openclaw-env.sh
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: loaded environment from /etc/profile.d/openclaw-env.sh"
fi
# ============================================
# 1. 启动 supervisord(管理 cron + openclaw-gateway)
# ============================================
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting supervisord..."
mkdir -p /var/run /var/log/supervisor /var/log/hf-entrypoint
/usr/bin/supervisord -c /etc/supervisor/supervisord.conf \
>> /var/log/hf-entrypoint/supervisord-stdout.log \
2>> /var/log/hf-entrypoint/supervisord-stderr.log &
SUPERVISORD_PID=$!
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: supervisord started (pid=$SUPERVISORD_PID)"
while [[ ! -f /var/run/supervisord.pid ]]; do
sleep 0.5
done
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: supervisord is ready"
# 1.1 等待 openclaw-gateway 完成备份恢复
# ============================================
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: waiting for openclaw-gateway to complete restore..."
RESTORE_COMPLETED_FILE="/tmp/openclaw-restore-completed"
OPENCLAW_LOG_FILE="/var/log/hf-entrypoint/openclaw-gateway-stdout.log"
RESTORE_LOG_FILE="/var/log/openclaw/restore.log"
WAITED=0
LAST_RESTORE_LINE=0
PROGRESS_CHECK_INTERVAL=20
mkdir -p "$(dirname "$RESTORE_LOG_FILE")"
show_restore_progress() {
if [[ -f "$RESTORE_LOG_FILE" ]]; then
local current_lines
current_lines=$(wc -l < "$RESTORE_LOG_FILE" 2>/dev/null || echo "0")
if [[ -n "$current_lines" ]] && [[ "$current_lines" -gt "$LAST_RESTORE_LINE" ]]; then
local new_lines=$((current_lines - LAST_RESTORE_LINE))
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: --- Restore log ($new_lines new lines) ---"
tail -n "$new_lines" "$RESTORE_LOG_FILE" | while IFS= read -r line; do
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $line"
done
LAST_RESTORE_LINE="$current_lines"
fi
fi
}
while true; do
# 首次进入循环时显示诊断信息
if [[ $WAITED -eq 0 ]]; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: waiting for restore completion..."
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: RESTORE_LOG_FILE=$RESTORE_LOG_FILE"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: RESTORE_COMPLETED_FILE=$RESTORE_COMPLETED_FILE"
fi
# 显示恢复日志进度
show_restore_progress
# 只检查恢复完成标志文件
if [[ -f "$RESTORE_COMPLETED_FILE" ]]; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: ✓ Restore completed"
# 显示恢复日志的最后几行
if [[ -f "$RESTORE_LOG_FILE" ]]; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: --- Final restore log ---"
tail -n 5 "$RESTORE_LOG_FILE" | while IFS= read -r line; do
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $line"
done
fi
rm -f "$RESTORE_COMPLETED_FILE"
break
fi
sleep 2
WAITED=$((WAITED + 2))
# 每n秒输出一次等待进度
if [[ $((WAITED % PROGRESS_CHECK_INTERVAL)) -eq 0 ]]; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: still waiting for restore... (${WAITED}s)"
show_restore_progress
fi
done
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: ✓ Restore wait completed (${WAITED}s), proceeding with PM2 startup"
# 1.2 确保 cron daemon 运行
if ! pgrep -x cron >/dev/null 2>&1; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting cron daemon..."
/usr/sbin/cron
fi
# ============================================
# 2. 启动 PM2 管理, 附加的 node 进程(如果需要)
# ============================================
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting PM2 for others..."
mkdir -p /root/.pm2 /var/log/hf-entrypoint
if grep -qE '"name"\s*:' /app/pm2/ecosystem.config.js 2>/dev/null; then
/usr/bin/pm2-runtime /app/pm2/ecosystem.config.js \
>> /var/log/hf-entrypoint/pm2-stdout.log \
2>> /var/log/hf-entrypoint/pm2-stderr.log &
PM2_PID=$!
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: PM2 started (pid=$PM2_PID)"
else
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: PM2: no applications defined in ecosystem.config.js, skipping..."
PM2_PID=""
fi
# ============================================
# 3. 检查 BT Panel 状态并配置自定义首页
# ============================================
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: checking BT Panel status..."
if [[ -f "/www/server/panel/default.pl" ]]; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: BT Panel is installed..."
# 启动宝塔面板
bt start
bt default
else
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: BT Panel not installed"
fi
# ============================================
# 4. 信号转发(确保 PID 1 的 SIGTERM 能传到 supervisord)
# ============================================
signal_handler() {
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: received SIGTERM, forwarding to supervisord..."
kill -TERM "$SUPERVISORD_PID" 2>/dev/null || true
kill -TERM "$PM2_PID" 2>/dev/null || true
}
trap signal_handler TERM INT QUIT
# ============================================
# 5. 启动 node hf-server.js 作为 PID 1
# ============================================
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting node server.js..."
cd /app
exec node hf-server.js