YYP0502 commited on
Commit
001e176
·
verified ·
1 Parent(s): 408eee3

Upload 3 files

Browse files
Files changed (3) hide show
  1. DEPLOY.md +6 -1
  2. scripts/health.py +7 -0
  3. scripts/start.sh +3 -1
DEPLOY.md CHANGED
@@ -46,4 +46,9 @@ JupyterLab 必须设置 Space Secret `JUPYTER_TOKEN`,打开实际 Space App
46
 
47
  若仍无法进入界面,请从 Hugging Face Space 的 Runtime logs 复制 `jupyter.log`/`nginx` 对应错误、以及浏览器网络请求的 HTTP 状态码(不要包含 token 或 API key)。
48
 
49
- QQ 白名单用户还可以发送 `/diag` 获取脱敏后的最近 bridge/startup/jupyter 日志;若机器人仍在线,优先用 `/status` 和 `/diag` 排查,无须进入 Jupyter Terminal。不要把诊断消息转发给其他人。容器的 Jupyter 与 QQ 日志默认保存在临时 data 目录;启动崩溃时会将脱敏后的最后几行写入 Space Runtime logs。
 
 
 
 
 
 
46
 
47
  若仍无法进入界面,请从 Hugging Face Space 的 Runtime logs 复制 `jupyter.log`/`nginx` 对应错误、以及浏览器网络请求的 HTTP 状态码(不要包含 token 或 API key)。
48
 
49
+ QQ 白名单用户还可以发送 `/diag` 获取脱敏后的最近 bridge/startup/jupyter 日志;若机器人仍在线,优先用 `/status` 和 `/diag` 排查,无须进入 Jupyter Terminal。不要把诊断消息转发给其他人。容器的 Jupyter 与 QQ 日志默认保存在临时 data 目录;启动崩溃时会将脱敏后的最后几行写入 Space Runtime logs。
50
+
51
+ ## UptimeRobot 成功请求记录
52
+ 每次 `/health` 同时确认 Jupyter 可连接并返回 HTTP 200 后,服务会在 `/home/node/app/data/uptime-heartbeat.log` 追加一个 `.` 字符;启动时删除旧文件并重建为空文件。查看该文件的字符数即可判断成功到达的健康请求次数,例如 `wc -c data/uptime-heartbeat.log`。失败的请求、404 和 Jupyter 未启动时不会追加字符。该文件和 history 一样属于临时容器文件层,Space 重启后会丢失。
53
+
54
+ 这个日志只能证明请求到达了当前运行中的容器,不能让 Hugging Face 把 Space 视为永久活跃,也不能阻止平台按免费硬件的闲置策略休眠或回收。若 Space 已经休眠,UptimeRobot 的请求通常只能触发一次唤醒/返回启动中的状态,是否重新启动及响应时间由 Hugging Face 平台决定;请以 Space Runtime 状态和平台政策为准。
scripts/health.py CHANGED
@@ -2,8 +2,10 @@ import http.server
2
  import os
3
  import socket
4
  import sys
 
5
 
6
  PIDS = [int(p) for p in sys.argv[1:] if p.isdigit() and int(p) > 0]
 
7
 
8
  class Handler(http.server.BaseHTTPRequestHandler):
9
  def do_GET(self):
@@ -15,6 +17,11 @@ class Handler(http.server.BaseHTTPRequestHandler):
15
  os.kill(pid, 0)
16
  with socket.create_connection(("127.0.0.1", 8888), timeout=2):
17
  pass
 
 
 
 
 
18
  status, body = 200, b"ok\n"
19
  except OSError:
20
  status, body = 503, b"unavailable\n"
 
2
  import os
3
  import socket
4
  import sys
5
+ from pathlib import Path
6
 
7
  PIDS = [int(p) for p in sys.argv[1:] if p.isdigit() and int(p) > 0]
8
+ HEARTBEAT_FILE = Path(os.environ.get("HEARTBEAT_FILE", "/home/node/app/data/uptime-heartbeat.log"))
9
 
10
  class Handler(http.server.BaseHTTPRequestHandler):
11
  def do_GET(self):
 
17
  os.kill(pid, 0)
18
  with socket.create_connection(("127.0.0.1", 8888), timeout=2):
19
  pass
20
+ # One successful public health request produces exactly one byte.
21
+ HEARTBEAT_FILE.parent.mkdir(parents=True, exist_ok=True)
22
+ with HEARTBEAT_FILE.open("a", encoding="ascii") as heartbeat:
23
+ heartbeat.write(".")
24
+ heartbeat.flush()
25
  status, body = 200, b"ok\n"
26
  except OSError:
27
  status, body = 503, b"unavailable\n"
scripts/start.sh CHANGED
@@ -4,7 +4,9 @@ cd /home/node/app
4
  mkdir -p data workspace /tmp/nginx
5
  # Both chat history and Codex/Jupyter working files are ephemeral.
6
  find workspace -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
7
- rm -f data/history.json data/bridge.log data/codex-*.txt data/jupyter.log data/nginx.log data/startup.log
 
 
8
  exec > >(tee -a data/startup.log) 2>&1
9
  : "${JUPYTER_TOKEN:?Set JUPYTER_TOKEN in Space Secrets to access JupyterLab}"
10
  printf '%s startup begin\n' "$(date -Is)"
 
4
  mkdir -p data workspace /tmp/nginx
5
  # Both chat history and Codex/Jupyter working files are ephemeral.
6
  find workspace -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
7
+ rm -f data/history.json data/bridge.log data/codex-*.txt data/jupyter.log data/nginx.log data/startup.log data/health.log data/uptime-heartbeat.log
8
+ touch data/uptime-heartbeat.log
9
+ export HEARTBEAT_FILE=/home/node/app/data/uptime-heartbeat.log
10
  exec > >(tee -a data/startup.log) 2>&1
11
  : "${JUPYTER_TOKEN:?Set JUPYTER_TOKEN in Space Secrets to access JupyterLab}"
12
  printf '%s startup begin\n' "$(date -Is)"