02 · 重建与修复手册(新服务器 playbook)

02 · 重建与修复手册(新服务器 playbook)

用途:下次在新机器上把整套东西重新搭起来,并逐步验证 ,避免再出现"四层连环故障"。

标注:【已验证】 = 2026-10-21 在真机上跑通过;【未验证】 = 依据 DRfC 源码推导,首次执行需留意。

配套:01-事件与根因复盘.md(为什么有这些步骤)、04-源码与配置存档.md(要抄的代码)。


0. 开工前先定 5 件事

# 决策 建议 理由
1 要不要 GPU 要。至少 T4 / 2080 级、8GB+ 显存 原机器 4 vCPU 无 GPU,而节奏表按 GPU 45min/轮设计,CPU 上 180 episodes 跑不满 → 每轮白烧 1 小时【已证实】
2 swarm 还是 compose 单机就 swarm (DR_DOCKER_STYLE=swarm) 与现有脚本一致;compose 要改 DR_MINIO_COMPOSE_FILE 等多处
3 数据放哪 MinIO 数据目录挂独立数据盘,不与系统盘共用 原机器 40G 系统盘,一轮训练 +843M,整机释放即全丢
4 镜像从哪来 国内拉 Docker Hub 慢时,先 docker pull 到私有 registry,或 docker save/load 离线包 曾出现"镜像 tag 变 <none> 导致 swarm 拒绝调度"
5 代码放哪 自研代码先建 git 仓库(本地或私有远端) 这次整机释放,AutoTrainTools 差点永久丢失

新机规格参考(原机纪录) :Ubuntu 22.04.2 LTS / 4 vCPU / 15GB / 40GB,Docker 24.0.2,Python 3.10.6。


1. 系统准备【未验证:本次未重装系统】

bash 复制代码
# 1.1 基础工具
apt update && apt install -y git curl jq unzip python3-pip python3-venv \
    openssl net-tools htop ncdu

# 1.2 Docker
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
docker version                       # 期望:Client/Server 都有版本号

# 1.3 Docker Swarm(单节点)
docker swarm init --advertise-addr <本机内网IP>
docker node ls                       # 期望:本节点 Ready / Active / Leader

# 1.4 关键:placement label(DRfC 的 stack 硬依赖)
NODE=$(docker node inspect self --format '{{.ID}}')
docker node update --label-add Sagemaker=true $NODE
docker node update --label-add Robomaker=true $NODE
docker node inspect self --format '{{json .Spec.Labels}}'
# 期望:{"Robomaker":"true","Sagemaker":"true"}

# 1.5 关键:swarm 作用域 overlay 网络(compose 里声明为 external)
docker network create sagemaker-local -d overlay --attachable --scope swarm
docker network ls | grep sagemaker-local     # 期望:sagemaker-local  overlay  swarm

# 1.6 AWS CLI(DRfC 用它访问 MinIO)
apt install -y awscli || pip3 install awscli
aws --version

为什么 1.4 / 1.5 要单独做 :bin/init.sh 里也会做这两件事,但它同时会重建网络、重置 env、重新 pull 镜像,属于破坏性操作。手动做这两步可以反复执行,不会误删东西。


2. 部署 DRfC 框架【部分已验证:源可用;安装步骤未在新机验证】

bash 复制代码
# 2.1 拿代码(三选一)
#    a) 本地已有副本(推荐,省流量):把 E:\Deepracer\deepracer-for-cloud 打包上传
#    b) 官方仓库
git clone https://github.com/aws-deepracer-community/deepracer-for-cloud.git
#    c) 与服务端同版本(当时是 v5.1.0-4-g6ac72fd)
cd deepracer-for-cloud && git checkout v5.1.0

# 2.2 放到约定路径(脚本里写死了 /home/rambo)
mkdir -p /home/rambo
mv deepracer-for-cloud /home/rambo/

# 2.3 配 system.env(部署级)------ 完整内容见 04 文档
cd /home/rambo/deepracer-for-cloud
cp system.env system.env.bak
#   DR_CLOUD=local
#   DR_DOCKER_STYLE=swarm
#   DR_SAGEMAKER_IMAGE=5.1.0-cpu        ← 有 GPU 改成 5.1.0-gpu
#   DR_ROBOMAKER_IMAGE=5.1.0-cpu-avx2   ← 有 GPU 改成 5.1.0-gpu
#   DR_COACH_IMAGE=5.1.0
#   DR_MINIO_IMAGE=RELEASE.2023-06-23T20-26-00Z   ← 本地固定 tag,不能 pull latest
#   DR_LOCAL_S3_BUCKET=bucket
#   DR_LOCAL_S3_PROFILE=minio
#   DR_WORKERS=1

# 2.4 配 run.env(实验级)------ 完整内容见 04 文档
#   DR_WORLD_NAME=reinvent_base
#   DR_LOCAL_S3_MODEL_PREFIX=reinvent_base-10000
#   DR_LOCAL_S3_PRETRAINED=False
#   DR_EVAL_NUMBER_OF_TRIALS=3
#   ★ term_cond_max_episodes 在 hyperparameters 模板里(CPU 上建议 30~50)

# 2.5 目录与 S3 凭据
mkdir -p data/minio/bucket custom_files log
aws configure --profile minio          # 填任意 AccessKey/Secret,region=us-east-1
#   (bin/init.sh 也会用 openssl rand 自动生成并写入该 profile)

# 2.6 Python 依赖
python3 -m venv /root/.virtualenvs/deepracer
source /root/.virtualenvs/deepracer/bin/activate
pip install -r requirements.txt
pip install imap-tools beautifulsoup4 glob2 openpyxl matplotlib pandas numpy
deactivate

3. 恢复自研 tools【代码需从 04 文档抄】

目标目录结构(脚本里的绝对路径都指向这里):

复制代码
/home/rambo/tools/
├── AutoTrainTools/
│   ├── AutomaticSignal.py          ← 主控状态机(04 有 ~95% 骨架)
│   ├── DeepracerFunction.py        ← 业务函数库(04 有 ~80%)
│   ├── reward_function_define.py   ← 奖励算法(04 近乎全文)
│   ├── reward_function_format.py   ← 奖励模板(需重写,接口见 04)
│   ├── model_metadata.json         ← 模板(04 全文)
│   ├── hyperparameters.json        ← 模板(04 全文)
│   ├── __init__.py
│   └── log/                        ← 运行时自动创建
├── CalculateLine/                  ← 本地 E:\Deepracer\Deepracer\CalculateLine 可直接上传
├── Competition/                    ← 同上
├── bashAPI.sh                      ← Shell 状态 API(04 有 ~90%)
├── init.sh                         ← Shell 函数库(04 有 ~60%)
├── HouseKeeping.sh                 ← 每日清理(04 有 ~30%,其余按功能重写)
├── APIFunction.py                  ← 邮件/日志/IO(04 全文)
├── receiveMail.py                  ← 邮件指令入口(04 全文,**建议不要启用**)
├── UserDefineFunction.py           ← 几何库(Deepracer\CalculateLine\UserDefineFunction.py 有)
└── LICENSE

3.1 环境变量(每个登录 shell 生效)

bash 复制代码
cat > /etc/profile.d/deepracer.sh <<'EOF'
#!/usr/bin/bash
export WORKON_HOME=/root/.virtualenvs
export TOOL_HOME=/home/rambo/tools
export TOOL_LOG=/home/rambo/tools/AutoTrainTools/log
export DR_HOME=/home/rambo/deepracer-for-cloud
export DR_BUCKET=$DR_HOME/data/minio/bucket
EOF
chmod +x /etc/profile.d/deepracer.sh

原文件里还有 virtualenvwrapper 包装和 source $TOOL_HOME/init.sh 自动加载,属于便利性封装;最小可用只需上面 5 个变量。

3.2 可执行权限

bash 复制代码
chmod +x /home/rambo/tools/*.sh /home/rambo/deepracer-for-cloud/*.sh

4. 启动 / 修复流程(本次实战验证过的顺序)

每一步都有"期望输出"。不满足期望就别往下走,否则后面的现象会像另一起故障。

Step 1 · swarm 健康

bash 复制代码
docker info 2>&1 | grep -A4 -i '^ *Swarm:'

期望 :Swarm: active + Is Manager: true。不是 → 做第 5 节"swarm 重建"。

Step 2 · 网络与 label

bash 复制代码
docker network ls | grep sagemaker-local
docker node inspect self --format '{{json .Spec.Labels}}'

期望 :sagemaker-local overlay swarm;{"Robomaker":"true","Sagemaker":"true"}。

缺哪个补哪个(1.4 / 1.5 的命令)。

Step 3 · 镜像齐全

bash 复制代码
docker images | grep -E 'deepracer|minio'

期望 :4 个镜像都有非 <none> 的 tag 。

是 <none> → docker tag <IMAGE_ID> <repo>:<tag>(别指望 swarm 自动 pull)。

Step 4 · 起 MinIO

bash 复制代码
cd /home/rambo/deepracer-for-cloud
source /etc/profile.d/deepracer.sh
source bin/activate.sh           # 会自动 docker stack deploy ... s3
docker service ls | grep s3_minio
nc -zv 127.0.0.1 9000

期望 :s3_minio 1/1 + 9000 端口通。

0/1 → docker service ps s3_minio --no-trunc,看 ERROR 列(多为 No such image)。

Step 5 · 起训练栈

bash 复制代码
dr-start-training -w             # ⚠ -w = 清空 s3://bucket/<MODEL_PREFIX>!
docker service ls

期望 :deepracer-0_rl_coach / deepracer-0_robomaker 都是 1/1(首次可能先 0/1,等 1-2 分钟)。

rl_coach 起不来 → docker service logs deepracer-0_rl_coach --tail 30,最常见是连不上 http://minio:9000。

Step 6 · 确认 algo-1 出现(这一步才算真在训练)

bash 复制代码
docker ps --format '{{.Names}} | {{.Status}}' | grep algo
/home/rambo/tools/bashAPI.sh getDRFCode

期望 :有 tmpXXXX_algo-1-XXXX_1 在跑;状态码 1110 。

1000 → algo 未起(看 rl_coach 日志);0110 → robomaker 掉了(docker service update --force deepracer-0_robomaker)。

Step 7 · 挂上自动化

bash 复制代码
crontab -e
# */1 * * * * /home/rambo/deepracer-for-cloud/keepAlive.sh
# 00 00 * * * /home/rambo/tools/HouseKeeping.sh

tail -f /home/rambo/tools/AutoTrainTools/log/$(date +%F).log

期望 :出现 2.upload-custom-files → 3. code is [1110] → 3.1 training 3600s, in sleep。

Step 8 · 前 10 分钟观察点

bash 复制代码
uptime                                  # load 应 4~8;接近 0 说明没在仿真
top -bn1 | head -8                      # 应看到 gzserver 吃满 1 核
docker logs --tail 20 $(docker ps -q -f name=algo)

期望 :saved intermediate frozen graph: .../model_0.pb、[s3] Successfully uploaded .ready。


5. 故障时的定向修复(本次实战路径)

5.1 Swarm 重建(拆房子级操作,先备份)

bash 复制代码
mkdir -p /root/backup
tar -czf /root/backup/swarm-state-$(date +%Y%m%d-%H%M%S).tgz -C /var/lib/docker swarm

docker swarm leave -f
docker swarm init --advertise-addr <内网IP>

# 重建后三件事必须补齐,缺一不可:
NODE=$(docker node inspect self --format '{{.ID}}')
docker node update --label-add Sagemaker=true $NODE
docker node update --label-add Robomaker=true $NODE
docker network create sagemaker-local -d overlay --attachable --scope swarm

leave -f 会删掉:swarm 作用域网络、节点 label、集群成员关系。这三样全要重建。

5.2 服务起来了但 0/1

bash 复制代码
docker service ps <svc> --no-trunc      # 只有这个能看到 Rejected 原因
ERROR 处置
No such image: minio/minio:latest docker tag <img_id> minio/minio:latest
无 ERROR 但一直 0/1 查 label 是否齐全
容器反复重启 docker service logs <svc> 看业务报错

5.3 rl_coach 报 EndpointConnectionError

bash 复制代码
docker service ls | grep s3_minio        # 必须 1/1
nc -zv 127.0.0.1 9000
docker exec <minio容器> sh -c 'ls /data'

MinIO 没起来或网络没建 → 回到 Step 4。

5.4 robomaker 报 Master node could be dead / exit 143

顺序错了:robomaker 依赖 rl_coach 的 ROS master。正确顺序:

bash 复制代码
docker service update --force deepracer-0_rl_coach     # 先
sleep 30
docker service update --force deepracer-0_robomaker    # 后

6. 必须补的巡检(这次事故的直接产物)

教训:证书过期 3 年无人发现,重启才暴露。没有巡检的系统等于没上监控。

建议写 tools/HealthCheck.sh,挂 cron 每天一次(或每小时),检查项与告警条件:

检查项 命令 告警条件
swarm 状态 `docker info grep 'Swarm:'`
节点证书剩余天数 openssl x509 -in /var/lib/docker/swarm/certificates/swarm-node.crt -noout -enddate < 30 天
节点 label docker node inspect self --format '{``{json .Spec.Labels}}' 缺 Sagemaker/Robomaker
网络存在 `docker network ls grep sagemaker-local`
服务 replicas docker service ls --format '{``{.Name}} {``{.Replicas}}' 任一不是 1/1
训练状态码 bashAPI.sh getDRFCode 连续 N 次不是 1110/1001
自动化进程 `ps -eo cmd grep -c AutomaticSignal`
磁盘 `df -h / tail -1`
数据备份 检查最近备份时间戳 > 7 天

复用现成的 APIFunction.sendmail(subject, content) 发邮件即可。


7. 数据备份(血的教训)

原机器整机释放 → data/minio/bucket(843M 模型/轨迹/指标)、/home/rambo 全部代码、tools.tar.zip 一起消失。

"同一台机器上的备份等于没有备份。"

新机器的最低要求:

bash 复制代码
# 7.1 代码进 git(最重要,注意排除大目录)
cd /home/rambo/tools && git init && cat > .gitignore <<'EOF'
__pycache__/
*.pyc
AutoTrainTools/log/
CalculateLine/image/
CalculateLine/routes/
EOF
git add -A && git commit -m "init: restore AutoTrainTools"
git remote add origin <你的私有仓库> && git push -u origin master

# 7.2 MinIO 数据定期打包到**本机之外**
tar -czf /mnt/backup/bucket-$(date +%F).tgz -C /home/rambo/deepracer-for-cloud/data/minio bucket
#   /mnt/backup 必须是独立云盘 / OSS 挂载点 / rsync 到另一台机器

# 7.3 关键产物单独取回(模型 .pb 才是最终成果)
aws --profile minio --endpoint-url http://localhost:9000 \
    s3 sync s3://bucket/<MODEL_PREFIX>/model /mnt/backup/model-<MODEL_PREFIX>/

注意 gzip 压缩比 :bucket 里大量是 CSV/JSON 文本,压缩后大约 1/8 ~ 1/10(843M → 100M 左右),适合打包。


8. 优化待办(重建时直接做掉,不要先复现故障)

P0 · 稳定性(必须在第一次训练前完成)

  • handler.sh 不要吞 stderr
    现状:coproc startTrain { dr-start-training -w ; } → 报错全丢
    改法:coproc startTrain { dr-start-training -w >>$DR_HOME/log/dr-actions.log 2>&1; }
  • AutomaticSignal.py 失败策略改成退避 + 单次告警
    现状:连续 30 次失败 → sendmail + sys.exit() → cron 1 分钟内重启 → 每 30 分钟一封邮件死循环
    改法:指数退避 + 只在"状态发生变化"时发一封 + 用一个 state 文件记录是否已告警
  • 加 HealthCheck.sh + cron(第 6 节清单)

P1 · 效果(决定训练有没有意义)

  • term_cond_max_episodes 按算力设定:CPU 上 30~50;GPU 上可保持 180
  • 启用完整几何奖励函数 :确认 generateFormatFile() 用 Py/Py4/<track>-<N>.py 的 waypoint,而不是占位版
  • handleTraining 的相对路径改成绝对路径 :rootFoler 已经在全局定义,直接拼绝对路径,避免依赖 CWD

P2 · 安全与整洁

  • 邮箱授权码出源码(改环境变量 / 权限 600 的配置文件)
  • eval(readFile(json)) → json.loads
  • receiveMail.py(邮件当指令入口)默认不启用
  • 删除死代码 killAutomaticIterate(引用的 AutomaticIterate.py 并不存在)
  • SSH:仅密钥认证 + 安全组按需放行(注意 :本次就是因为把 IP 锁死 + ISP 换 IP 导致 Connection timed out,建议放通网段或加动态 IP 更新脚本)

9. 附录 · 一键整备脚本骨架【未验证,首次运行请分步执行】

bash 复制代码
#!/bin/bash
# bootstrap.sh ------ 新机器一次性整备(建议逐段执行,不要整体盲跑)
set -euo pipefail

INNER_IP=${1:?用法: bootstrap.sh <内网IP>}
DR_HOME=/home/rambo/deepracer-for-cloud
TOOL_HOME=/home/rambo/tools

echo "== 1. 基础工具 =="
apt update && apt install -y git curl jq unzip python3-pip python3-venv openssl net-tools

echo "== 2. Docker + Swarm =="
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
docker info | grep -q 'Swarm: active' || docker swarm init --advertise-addr "$INNER_IP"

echo "== 3. placement label =="
NODE=$(docker node inspect self --format '{{.ID}}')
docker node update --label-add Sagemaker=true "$NODE"
docker node update --label-add Robomaker=true "$NODE"

echo "== 4. overlay 网络 =="
docker network ls | grep -q sagemaker-local || \
  docker network create sagemaker-local -d overlay --attachable --scope swarm

echo "== 5. 目录 =="
mkdir -p "$DR_HOME"/data/minio/bucket "$DR_HOME"/custom_files "$DR_HOME"/log "$TOOL_HOME"

echo "== 6. 环境变量 =="
grep -q TOOL_HOME /etc/profile.d/deepracer.sh 2>/dev/null || cat > /etc/profile.d/deepracer.sh <<'EOF'
#!/usr/bin/bash
export WORKON_HOME=/root/.virtualenvs
export TOOL_HOME=/home/rambo/tools
export TOOL_LOG=/home/rambo/tools/AutoTrainTools/log
export DR_HOME=/home/rambo/deepracer-for-cloud
export DR_BUCKET=$DR_HOME/data/minio/bucket
EOF
chmod +x /etc/profile.d/deepracer.sh

echo "== 7. Python venv =="
python3 -m venv /root/.virtualenvs/deepracer
/root/.virtualenvs/deepracer/bin/pip install -q --upgrade pip
/root/.virtualenvs/deepracer/bin/pip install -q imap-tools beautifulsoup4 glob2 openpyxl matplotlib pandas numpy

echo "== 8. 校验 =="
docker info | grep -A3 'Swarm:'
docker node inspect self --format '{{json .Spec.Labels}}'; echo
docker network ls | grep sagemaker-local
echo "OK ------ 接下来手工: 拷贝 deepracer-for-cloud / tools,配 system.env+run.env,然后走 02 文档第 4 节"

10. 第二次实战(2026-10-21 04:00 起)新增的修复项

这次是在"2023 年镜像 + 同 IP 新实例"上重做,多踩了 4 个上次没遇到的坑,全部已修,下次重建请直接带上。

10.1 开机瞬间就要防数据被清(最高优先级)

现象 :实例一启动,镜像里的 crontab 就已经有 */1 * * * * keepAlive.sh,立刻拉起 AutomaticSignal.py。而它第一步就是 dr-start-training -w。

为什么第一次没清 :minio 还没起 → aws s3 ls s3://bucket/<prefix> 失败 → S3_FILES=0 → 跳过 WIPE。

为什么后来清了 :我把 minio 拉起来后的下一分钟 ,WIPE 就真的执行了 → reinvent_base-10000 从 843M 变 20K(丢 274M)。

正确顺序(务必照做):

bash 复制代码
# 1. 先停掉看门狗
crontab -l > /root/backup/crontab.bak
crontab -l | sed 's|^\*/1 \* \* \* \* /home/rambo/deepracer-for-cloud/keepAlive.sh|#&|' | crontab -
pkill -f 'AutomaticSignal.py'; pkill -f 'keepAlive.sh'; pkill -f 'TRGHND.sh'
# 2. 备份数据
nohup tar -czf /root/backup/bucket.tgz -C /home/rambo/deepracer-for-cloud/data/minio bucket &
# 3. 再修 swarm / network / label / minio
# 4. 最后才恢复 cron
sed -i 's|^#\(\*/1 \* \* \* \* .*keepAlive.sh\)|\1|' <(crontab -l) | crontab -

教训:先把会写数据的进程全部停掉,再动基础设施。 上次是在"服务已停"的机器上修,所以没遇到;这次是在"自动化一直活着"的机器上修,就被反咬了一口。

10.2 TRGHND.sh 会 100% 占一个核

现象:

复制代码
PID 23768  root  bash TRGHND.sh   %CPU 93~100   累积 0:56

原因 :keepAlive.sh 用 coproc TRGHND { bash TRGHND.sh ;} 启动,cron 环境下没有 tty,stdin 立刻 EOF →

while true; do read; done 里 read 立即返回失败 → 变成纯忙循环。

修复(改成不依赖 stdin,信号照样能打断 sleep):

bash 复制代码
while true
do
    sleep 1
done

10.3 keepAlive.sh 的"count ≠ 1 就全杀"会自我拆台

现象 :keepAlive.log 反复出现

复制代码
[checkTRGHND],count is [2],jobs [23768 25092]
[checkTRGHND],jobs [27184 27189]        ← 新起的也随即消失

原因 :用 coproc 启动的 TRGHND 是 keepAlive 的子进程,keepAlive 退出时被带走;下一分钟又判定 count=0 再起一个,而 count>1 分支会连健康的实例一起 kill -9。

修复 :改为完全脱离父进程启动(这样 count 才能稳定为 1):

bash 复制代码
      # 旧: coproc TRGHND { bash TRGHND.sh ;}
      setsid nohup bash TRGHND.sh >/dev/null 2>&1 < /dev/null &

10.4 Step 3 的重试策略会每 60 秒 WIPE 一次

现象:

复制代码
[04:13:23] 3.Preparation Training
[04:14:23] 3. code is [0110]                      ← robomaker 还在启动
[04:14:23] 3.Preparation Training again -[1/30]   ← 立刻又发 start-training

原因 :robomaker 从创建到 Running 需要 60~90 秒 ,这段时间状态码是 0110/1000;而原逻辑是 if code != '1110': 重发 start-training → 每次重发都带 -w → 每 60 秒清空一次模型目录并重启整套。这正是 274M 被迅速清空的放大器。

修复 :只有在"什么都没起(0000)"时才重发;只要有容器在跑就认为部署中,直接继续等。

python 复制代码
              if code == '0000':          # 原: if code != '1110'
                  log(3, f'3.Preparation Training again -[{i+1}/30]')
                  sendSignal("35", 60)
              else:
                  break

10.5 本次实际改动文件汇总

文件 改动 备份
AutoTrainTools/AutomaticSignal.py ①/60→/30 ②去掉未定义的 j ③Step3 重试条件改 == '0000' .bak.20261021-040955
TRGHND.sh while read → while sleep 1 TRGHND.sh.bak* / .bak2*
keepAlive.sh coproc → setsid nohup ... &(2 处) keepAlive.sh.bak*
minio/minio:latest 悬空 tag 重新打(镜像 a5d29c2476d0) ------

10.6 ★启动握手文件 ip/:-w 重试会把它们删掉

背景:DRfC 的启动握手是「algo-1 起 Redis → 把 IP 写到 S3 → robomaker 轮询拿到 IP 才连上去开仿真」。

ip/ 下必须有三个对象(2023 年成功跑的参照物在 reinvent_base-001/ip/):

对象 内容 大小
ip.json {"IP": "10.0.1.23"}(algo-1 的容器 IP) 19 B
hyperparameters.json 本轮超参 ~340 B
done 字符串 done 4 B

故障表现:

bash 复制代码
bashAPI.sh getDRFCode   # → 1110  ← 骗子!三个容器都在
bashAPI.sh getEpisode   # → 0     ← 一圈都没跑
docker service logs deepracer-0_robomaker
#   Waiting for SageMaker Redis server IP: Time elapsed: 1065 seconds
aws ... s3 ls s3://bucket/<prefix>/ip/     # → 空(目录都不存在)

根因 :dr-start-training -w 里的 aws s3 rm --recursive s3://bucket/<prefix> 删的是整个前缀 ,包括 algo-1 刚写好的 ip/。而 Step3 的旧重试逻辑(if code != '1110')会在 robomaker 启动的 60~90 秒里再发一次 -w → 握手文件被抹掉 → robomaker 永远等不到。

这正是 10.4 那条补丁要解决的:只要打过 Step3 补丁(仅 0000 才重发),就不会再触发。

补救(不重启整个训练):

bash 复制代码
AL=$(docker ps --format '{{.Names}}' | grep algo | head -1)
IP=$(docker inspect $AL --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}')
printf '{"IP": "%s"}' "$IP" > /tmp/ip.json
cp /home/rambo/deepracer-for-cloud/custom_files/hyperparameters.json /tmp/hp.json
printf 'done' > /tmp/donemarker
S3="aws --profile minio --endpoint-url http://localhost:9000 s3"
$S3 cp /tmp/ip.json s3://bucket/<MODEL_PREFIX>/ip/ip.json
$S3 cp /tmp/hp.json s3://bucket/<MODEL_PREFIX>/ip/hyperparameters.json
$S3 cp /tmp/donemarker s3://bucket/<MODEL_PREFIX>/ip/done
docker service update --force deepracer-0_robomaker     # 它已 exit 143,必须重启

判断"到底有没有在训练"的可靠信号(别只看 1110):

bash 复制代码
bashAPI.sh getEpisode                              # 应逐渐增长
curl -s -m 4 "http://127.0.0.1:8080/stream?topic=/racecar/deepracer/kvs_stream" | wc -c
#   健康时 6 秒能收 ~2.4 MB;没在训练时只有 22 字节

完整时序与证据见 changelog/2026-10-21-cpu-instance-rebuild.md 第 10 节。

10.7 ★KEEP_MODEL:从根上避免"重启训练就清空历史"

10.6 的竞态根源是 -w 会清空整个前缀。彻底解决不是"记得先备份",而是把这层语义做成开关。

新版 handler.sh (docs/scripts/handler.sh,由 restore.sh 第 6d 步自动安装)在收到 35 号信号时:

复制代码
KEEP_MODEL=1(默认)
  └─ aws s3 mv s3://bucket/<prefix>/ → s3://bucket/_archive/<prefix>-<时间戳>/ --recursive
       ├─ 成功 → dr-start-training -w   (前缀已空,-w 删不到东西)
       └─ 失败 → 中止启动 + 写日志        (宁可不训练,也不丢数据)
KEEP_MODEL=0
  └─ 原行为:直接 -w

开关文件 /home/rambo/tools/auto.env(restore.sh 第 6e 步写入):

ini 复制代码
KEEP_MODEL=1        # 1=先归档;0=直接清空
KEEP_ARCHIVES=3     # 保留最近几份归档;<=0 不清理

同时修掉的 P0 :原版 6 个分支的 coproc 全都没有重定向,dr-* 的 stdout/stderr 全丢(45 分钟静默的元凶)。新版统一 >> log/dr-actions.log 2>&1,出问题第一时间看这个文件。

归档清理与恢复:

bash 复制代码
# 现有归档
aws --profile minio --endpoint-url http://localhost:9000 s3 ls s3://bucket/_archive/

# 恢复某一份(先停训练)
dr-stop-training
aws --profile minio --endpoint-url http://localhost:9000 s3 cp \
    s3://bucket/_archive/reinvent_base-10000-20261021-041455/ \
    s3://bucket/reinvent_base-10000/ --recursive

磁盘注意:每份归档 ≈ 当前模型前缀的体积(实测 ~270MB),KEEP_ARCHIVES=3 大约占 800MB。

相关推荐
李纲明1 小时前
WordPress 报建立数据库连接时出错:先核 wp-config 四元组,再查 MySQL 服务与表修复
运维·数据库·mysql·wordpress·排障·devdiy
EVEN-09131 小时前
Linux-IPC进程间通信
linux·运维·服务器
徐小黑ACG1 小时前
docker 基础教程
运维·docker·容器
多弗朗皮卡丘1 小时前
Linux 进程信号
linux·运维·服务器
qeen871 小时前
【Linux】动静态库的链接与加载过程
linux·运维·系统编程
好啊好啊郝!2 小时前
计算机网络最基础知识点
服务器·网络·计算机网络
重生之小比特2 小时前
【Linux系统】17 库制作与原理(上)
linux·运维·服务器
Shadow(⊙o⊙)3 小时前
仿muduo实现高并发服务器——EchoServer完成
运维·服务器
Brilliantwxx3 小时前
【STM32】 内部 Flash 的 HAL 库函数详解与自定义封装实战
linux·服务器·网络