SZFSPC commited on
Commit
396eb8e
·
verified ·
1 Parent(s): 2bfa191

fix: improve SSH service stability and backup.py error handling

Browse files
Files changed (1) hide show
  1. scripts/hf-entrypoint.sh +41 -10
scripts/hf-entrypoint.sh CHANGED
@@ -94,12 +94,26 @@ fi
94
  # ============================================
95
  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting supervisord..."
96
  mkdir -p /var/run /var/log/supervisor /var/log/hf-entrypoint
 
97
  /usr/bin/supervisord -c /etc/supervisor/supervisord.conf \
98
- >> /var/log/hf-entrypoint/supervisord-stdout.log \
99
- 2>> /var/log/hf-entrypoint/supervisord-stderr.log &
100
  SUPERVISORD_PID=$!
101
  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: supervisord started (pid=$SUPERVISORD_PID)"
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  while [[ ! -f /var/run/supervisord.pid ]]; do
104
  sleep 0.5
105
  done
@@ -410,6 +424,7 @@ SLOW_WARN_THRESHOLD=900 # 15分钟超时预警
410
  MAX_WAIT_TIMEOUT=28800 # 最大等待28800秒(8小时),超时后强制继续启动
411
  IDLE_WARN_THRESHOLD=120 # 日志无新内容120秒则告警
412
  TIME_NO_NEW_LOG=0
 
413
 
414
  mkdir -p "$(dirname "$RESTORE_LOG_FILE")"
415
 
@@ -423,9 +438,10 @@ show_restore_progress() {
423
 
424
  if [[ -n "$current_lines" ]] && [[ "$current_lines" -gt "$LAST_RESTORE_LINE" ]]; then
425
  local new_lines=$((current_lines - LAST_RESTORE_LINE))
426
- echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] hf-entrypoint: --- Restore log ($new_lines new lines) ---"
427
  # FAST: use awk to prefix lines in a single call (no bash while-read loop)
428
- tail -n "$new_lines" "$RESTORE_LOG_FILE" | awk -v ts="[$(date -u +"%Y-%m-%dT%H:%M:%SZ")]" '{print ts, $0}'
 
429
  LAST_RESTORE_LINE="$current_lines"
430
  TIME_NO_NEW_LOG=0
431
  fi
@@ -494,27 +510,35 @@ while true; do
494
  # 使用 supervisorctl status 作为权威检查,同时检查实际进程名作为兜底
495
  # 注意: supervisord 中命令是 openclaw-entrypoint.sh gateway,不包含字符串 "openclaw-gateway"
496
  # 因此 pgrep -f "openclaw-gateway" 永远不匹配,必须检查实际的进程名
 
497
  gateway_alive=false
498
  if [[ -f "/var/run/supervisord.pid" ]]; then
499
  # 方法1: 用 supervisorctl 检查 program 状态(最权威,匹配 program:openclaw-gateway)
 
500
  if command -v supervisorctl >/dev/null 2>&1; then
501
- svc_status=$(supervisorctl status openclaw-gateway 2>/dev/null)
502
  if echo "$svc_status" | grep -qE "(RUNNING|STARTING)"; then
503
  gateway_alive=true
504
  fi
505
  fi
506
  # 方法2: 兜底检查 - 检查实际运行的入口脚本或恢复进程
 
507
  if [[ "$gateway_alive" != true ]]; then
508
- if pgrep -f "openclaw-entrypoint" >/dev/null 2>&1 \
509
- || pgrep -f "backup\.py restore" >/dev/null 2>&1 \
510
- || pgrep -f "openclaw-restore" >/dev/null 2>&1; then
511
  gateway_alive=true
512
  fi
513
  fi
514
  fi
 
 
 
515
  if [[ "$gateway_alive" != true ]]; then
516
  # 如果 gateway 进程已经不存在,且未看到完成标志,视为恢复失败
517
- if [[ ! -f "$RESTORE_COMPLETED_FILE" ]] && [[ $WAITED -gt 10 ]]; then
 
 
518
  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: ✗ openclaw-gateway process exited before restore completed, marking as failed"
519
  # 在退出前转储完整的恢复日志,让用户看到崩溃前发生了什么
520
  _dump_restore_logs "gateway process exited during restore (waited ${WAITED}s)"
@@ -558,6 +582,13 @@ while true; do
558
  if [[ -f "$OPENCLAW_STDERR_LOG" ]]; then
559
  _dump_log_file "GATEWAY STDERR (hidden Python errors/warnings check)" "$OPENCLAW_STDERR_LOG" 100
560
  fi
 
 
 
 
 
 
 
561
  break
562
  fi
563
 
@@ -605,7 +636,7 @@ while true; do
605
  gw_stderr_size=$(stat -c%s "$OPENCLAW_STDERR_LOG" 2>/dev/null || echo "0")
606
  if [[ "$gw_stderr_size" -gt "0" ]]; then
607
  echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] hf-entrypoint: gateway-stderr (last 30 lines, ${gw_stderr_size} bytes total) --"
608
- tail -n 30 "$OPENCLAW_STDERR_LOG"
609
  echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] hf-entrypoint: -- end gateway-stderr"
610
  fi
611
  fi
 
94
  # ============================================
95
  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: starting supervisord..."
96
  mkdir -p /var/run /var/log/supervisor /var/log/hf-entrypoint
97
+ touch /var/log/hf-entrypoint/supervisord-stdout.log /var/log/hf-entrypoint/supervisord-stderr.log
98
  /usr/bin/supervisord -c /etc/supervisor/supervisord.conf \
99
+ > >(tee -a /var/log/hf-entrypoint/supervisord-stdout.log) \
100
+ 2> >(tee -a /var/log/hf-entrypoint/supervisord-stderr.log >&2) &
101
  SUPERVISORD_PID=$!
102
  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: supervisord started (pid=$SUPERVISORD_PID)"
103
 
104
+ # 启动后台 tail -f 进程,把 openclaw-gateway 的日志实时转发到容器 stdout/stderr
105
+ # 这样用户在 docker logs 中可以看到 restore 的所有输出
106
+ touch /var/log/hf-entrypoint/openclaw-gateway-stdout.log /var/log/hf-entrypoint/openclaw-gateway-stderr.log
107
+ if command -v tail >/dev/null 2>&1; then
108
+ # stdout: prefix with [gateway-out so users can distinguish
109
+ tail -f /var/log/hf-entrypoint/openclaw-gateway-stdout.log 2>/dev/null &
110
+ TAIL_STDOUT_PID=$!
111
+ # stderr: prefix with [gateway-err]
112
+ tail -f /var/log/hf-entrypoint/openclaw-gateway-stderr.log 2>/dev/null >&2 &
113
+ TAIL_STDERR_PID=$!
114
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: log forwarders started (stdout_pid=$TAIL_STDOUT_PID, stderr_pid=$TAIL_STDERR_PID)"
115
+ fi
116
+
117
  while [[ ! -f /var/run/supervisord.pid ]]; do
118
  sleep 0.5
119
  done
 
424
  MAX_WAIT_TIMEOUT=28800 # 最大等待28800秒(8小时),超时后强制继续启动
425
  IDLE_WARN_THRESHOLD=120 # 日志无新内容120秒则告警
426
  TIME_NO_NEW_LOG=0
427
+ gateway_was_seen_alive=false
428
 
429
  mkdir -p "$(dirname "$RESTORE_LOG_FILE")"
430
 
 
438
 
439
  if [[ -n "$current_lines" ]] && [[ "$current_lines" -gt "$LAST_RESTORE_LINE" ]]; then
440
  local new_lines=$((current_lines - LAST_RESTORE_LINE))
441
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: --- Restore log ($new_lines new lines) ---"
442
  # FAST: use awk to prefix lines in a single call (no bash while-read loop)
443
+ # 用 || true 保护管道,避免 set -o pipefail 触发脚本立即退出
444
+ tail -n "$new_lines" "$RESTORE_LOG_FILE" | awk -v ts="[$(date -u +%Y-%m-%dT%H:%M:%SZ)]" '{print ts, $0}' || true
445
  LAST_RESTORE_LINE="$current_lines"
446
  TIME_NO_NEW_LOG=0
447
  fi
 
510
  # 使用 supervisorctl status 作为权威检查,同时检查实际进程名作为兜底
511
  # 注意: supervisord 中命令是 openclaw-entrypoint.sh gateway,不包含字符串 "openclaw-gateway"
512
  # 因此 pgrep -f "openclaw-gateway" 永远不匹配,必须检查实际的进程名
513
+ # 关键: 所有检查命令必须用 || true 保护,避免 set -e 误触发脚本立即退出
514
  gateway_alive=false
515
  if [[ -f "/var/run/supervisord.pid" ]]; then
516
  # 方法1: 用 supervisorctl 检查 program 状态(最权威,匹配 program:openclaw-gateway)
517
+ # supervisorctl status 在 program 不存在或状态不是 RUNNING 时返回非0,必须用 || true
518
  if command -v supervisorctl >/dev/null 2>&1; then
519
+ svc_status=$(supervisorctl status openclaw-gateway 2>/dev/null || true)
520
  if echo "$svc_status" | grep -qE "(RUNNING|STARTING)"; then
521
  gateway_alive=true
522
  fi
523
  fi
524
  # 方法2: 兜底检查 - 检查实际运行的入口脚本或恢复进程
525
+ # pgrep 在无匹配时返回 1,在 if 条件中不会触发 set -e,但为了安全用 || true
526
  if [[ "$gateway_alive" != true ]]; then
527
+ if { pgrep -f "openclaw-entrypoint" >/dev/null 2>&1 || true; } \
528
+ || { pgrep -f "backup\.py restore" >/dev/null 2>&1 || true; } \
529
+ || { pgrep -f "openclaw-restore" >/dev/null 2>&1 || true; }; then
530
  gateway_alive=true
531
  fi
532
  fi
533
  fi
534
+ if [[ "$gateway_alive" == true ]]; then
535
+ gateway_was_seen_alive=true
536
+ fi
537
  if [[ "$gateway_alive" != true ]]; then
538
  # 如果 gateway 进程已经不存在,且未看到完成标志,视为恢复失败
539
+ # 规则: 1) 如果曾经看到 gateway alive(gateway_was_seen_alive=true),立即检测为崩溃
540
+ # 2) 如果���未看到 alive,等待 10 秒后再判定(确保 supervisord 有时间启动它)
541
+ if [[ ! -f "$RESTORE_COMPLETED_FILE" ]] && { [[ "$gateway_was_seen_alive" == true ]] || [[ $WAITED -gt 10 ]]; }; then
542
  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] hf-entrypoint: ✗ openclaw-gateway process exited before restore completed, marking as failed"
543
  # 在退出前转储完整的恢复日志,让用户看到崩溃前发生了什么
544
  _dump_restore_logs "gateway process exited during restore (waited ${WAITED}s)"
 
582
  if [[ -f "$OPENCLAW_STDERR_LOG" ]]; then
583
  _dump_log_file "GATEWAY STDERR (hidden Python errors/warnings check)" "$OPENCLAW_STDERR_LOG" 100
584
  fi
585
+ # 清理 tail 转发进程(避免继续写入 stdout 干扰后续日志)
586
+ if [[ -n "${TAIL_STDOUT_PID:-}" ]]; then
587
+ kill "$TAIL_STDOUT_PID" 2>/dev/null || true
588
+ fi
589
+ if [[ -n "${TAIL_STDERR_PID:-}" ]]; then
590
+ kill "$TAIL_STDERR_PID" 2>/dev/null || true
591
+ fi
592
  break
593
  fi
594
 
 
636
  gw_stderr_size=$(stat -c%s "$OPENCLAW_STDERR_LOG" 2>/dev/null || echo "0")
637
  if [[ "$gw_stderr_size" -gt "0" ]]; then
638
  echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] hf-entrypoint: gateway-stderr (last 30 lines, ${gw_stderr_size} bytes total) --"
639
+ tail -n 30 "$OPENCLAW_STDERR_LOG" 2>/dev/null || true
640
  echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] hf-entrypoint: -- end gateway-stderr"
641
  fi
642
  fi