试用前准备:全班模拟压测、评分并发 6→16、手动备份与恢复
- test/classroom.ts:45 个虚拟学生走一遍登录、运行、自测、提交,统计每个环节等多久 - 评分并发可配置(SIM_GRADE_CONCURRENCY,默认 16),提交队列同时评的份数跟着走; 2 核实测项目 8 任务 3 全班自测从约 4 分钟降到约 1.5 分钟 - 检查的默认等待 2 秒→5 秒,机器忙时不再误判正确的程序 - 删除学生时删除他的数据库(编号会重新用给新学生) - deploy/backup.sh、deploy/restore.sh:手动备份到宿主机 backups/,恢复前先备份 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e8058376dd
commit
982b1297aa
23 files changed
+479
-25
No files matched your search
@@ -103,8 +103,23 @@
|
||||
| 学生账号 | 老师登录后在"班级管理"里导入名单、查看和重置密码 |
|
||||
| 看日志 | `docker compose logs -f app` |
|
||||
| 看资源占用 | `docker stats` |
|
||||
| 备份数据 | `deploy/backup.sh`,见下文"备份与恢复" |
|
||||
| 重启 / 停止 | `docker compose restart` / `docker compose down` |
|
||||
|
||||
## 备份与恢复
|
||||
|
||||
平台不自动备份,在服务器的 `~/IOT_SIM` 下手动执行:
|
||||
|
||||
```bash
|
||||
deploy/backup.sh # 备份到 backups/<日期时间>/,平台运行中也可以,学生不受影响
|
||||
deploy/restore.sh backups/20261025-153000 # 用某份备份替换现在的全部数据
|
||||
```
|
||||
|
||||
- 备份包括账号、班级、学生作品、作业、提交、评阅(`iot-sim.db`)和每个学生自己的数据库(`databases/`)。一个班一学期的数据估计两三百 MB,主要是提交时的界面截图。
|
||||
- 备份放在宿主机的 `~/IOT_SIM/backups/` 里,不在 Docker 数据卷里,误删数据卷也还在;**要防服务器硬盘坏,把这个目录拷到别的机器上**。
|
||||
- 建议在部署大的新版本前、学期中间、期末导出成绩后各备份一次。
|
||||
- 恢复会先自动备份现在的数据(恢复错了还能换回来),然后停止平台约十几秒、替换数据、重新启动;正在运行的学生程序会结束,尽量不在上课时恢复。
|
||||
|
||||
## 可调参数
|
||||
|
||||
写在 `.env` 里,改完 `docker compose up -d` 生效。
|
||||
@@ -120,3 +135,4 @@
|
||||
| `SIM_HEAP_LIMIT_MB` | `128` | 每个学生程序的内存上限 |
|
||||
| `SIM_CPU_LIMIT_SECONDS` | `120` | 每次运行累计 CPU 时间上限(防死循环) |
|
||||
| `SIM_MAX_RUN_MINUTES` | `60` | 每次运行最长时间 |
|
||||
| `SIM_GRADE_CONCURRENCY` | `16` | 全站同时跑几个评分检查项(提交评分和"自己检查"共用)。2 核实测:45 人同时自测项目 8 任务 3,最后一人约 1.5 分钟出结果;调到 24 以上 CPU 不够,定时器来不及触发,正确的程序会被误判 |
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
# 在服务器上执行:备份平台的全部数据(账号、班级、学生作品、作业、提交、评阅,以及每个学生自己的数据库)
|
||||
# 到 backups/<日期时间>/。备份在宿主机上,不在 Docker 数据卷里,数据卷被删也还在;要防硬盘坏,把它拷到别的机器上。
|
||||
# 平台运行中也可以备份,学生不受影响。恢复见 deploy/restore.sh。
|
||||
# 用法:deploy/backup.sh
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
mkdir -p backups
|
||||
name=$(date +%Y%m%d-%H%M%S)
|
||||
# 同一秒里做了两次(如 restore.sh 恢复前先备份)时,等到下一秒,不和已有的备份重名
|
||||
while [[ -e backups/$name ]]; do
|
||||
sleep 1
|
||||
name=$(date +%Y%m%d-%H%M%S)
|
||||
done
|
||||
inside=/data/.backup-$name
|
||||
# 在容器里导出(SQLite 一致读取,不会备份出写了一半的库),再拷到宿主机
|
||||
docker compose exec -T app bun server.js backup "$inside" >/dev/null
|
||||
docker compose cp "app:$inside" "backups/$name" 2>/dev/null
|
||||
docker compose exec -T app rm -rf "$inside"
|
||||
echo "已备份到 $(pwd)/backups/$name($(du -sh "backups/$name" | cut -f1))"
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# 在服务器上执行:用 deploy/backup.sh 做的备份替换平台现在的全部数据。
|
||||
# 替换前先自动备份现在的数据(恢复错了还能换回来);恢复时平台停止约十几秒,正在运行的学生程序会结束。
|
||||
# 用法:deploy/restore.sh backups/<日期时间>
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
dir=${1:?用法:deploy/restore.sh backups/<日期时间>}
|
||||
if [[ ! -f $dir/iot-sim.db ]]; then
|
||||
echo "$dir 不是备份目录(里面应该有 iot-sim.db)"
|
||||
exit 1
|
||||
fi
|
||||
read -r -p "用 $dir 替换平台现在的全部数据?现在的数据会先备份。[y/N] " answer
|
||||
[[ $answer == y || $answer == Y ]] || exit 1
|
||||
|
||||
echo "== 备份现在的数据"
|
||||
deploy/backup.sh
|
||||
echo "== 停止平台、替换数据"
|
||||
docker compose stop app
|
||||
# 旧库的 -wal、-shm 文件一定要删掉,否则会被当成新库的未写完的日志,把恢复的库弄坏
|
||||
docker compose run --rm --no-deps -T -v "$(realpath "$dir"):/restore:ro" app \
|
||||
sh -c 'rm -rf /data/iot-sim.db /data/iot-sim.db-wal /data/iot-sim.db-shm /data/databases && cp -r /restore/. /data/'
|
||||
echo "== 启动平台"
|
||||
docker compose up -d app
|
||||
echo "已恢复到 $dir"
|
||||
Reference in new issue
Block a user