File size: 8,661 Bytes
a757bd3 | 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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | #!/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.0 启动 SSH 服务和看门狗(确保SSH持续可用)
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting SSH service and watchdog..."
# 0. 设置root密码(如果已设置ROOT_PASSWORD环境变量)
if [ -n "${ROOT_PASSWORD:-}" ]; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: setting root password..."
echo "root:${ROOT_PASSWORD}" | chpasswd 2>/dev/null
if [ $? -eq 0 ]; then
# 确保root账户未锁定
passwd -u root 2>/dev/null || true
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: root password set successfully"
else
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: WARNING: failed to set root password"
fi
fi
# 1. 确保SSH服务启动
if ! pgrep -x "sshd" > /dev/null 2>&1; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting sshd..."
if [ -x "/usr/sbin/sshd" ]; then
/usr/sbin/sshd
elif [ -x "/usr/bin/sshd" ]; then
/usr/bin/sshd
else
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: WARNING: sshd executable not found"
fi
sleep 2
fi
# 启动SSH看门狗(确保SSH服务持续可用)
if [ -x "/usr/local/bin/ssh_service_watchdog.sh" ]; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting SSH watchdog..."
# 将看门狗输出重定向到Docker标准输出,这样即使xterm无法连接,也可以通过docker logs查看
nohup /usr/local/bin/ssh_service_watchdog.sh >> /proc/1/fd/1 2>> /proc/1/fd/2 &
SSH_WATCHDOG_PID=$!
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: SSH watchdog started (pid=$SSH_WATCHDOG_PID)"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: SSH watchdog logs are available via: docker logs <container>"
else
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: WARNING: ssh_service_watchdog.sh not found"
fi
# 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
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 all processes..."
# 停止SSH看门狗
if [ -n "${SSH_WATCHDOG_PID:-}" ]; then
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: stopping SSH watchdog (pid=$SSH_WATCHDOG_PID)..."
kill -TERM "$SSH_WATCHDOG_PID" 2>/dev/null || true
fi
# 停止supervisord
kill -TERM "$SUPERVISORD_PID" 2>/dev/null || true
# 停止PM2
kill -TERM "$PM2_PID" 2>/dev/null || true
# 停止SSH服务
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: stopping SSH service..."
if pgrep -x "sshd" > /dev/null 2>&1; then
killall sshd 2>/dev/null || true
fi
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: all services stopped"
}
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 |