Jetson Image-based OTA:DevKit 从零跑通官方 Demo 实操指南(R36.4.x)

华为OD机试真题 2026.11.4. 新系统 【河流水系流量评估】 华为OD机试真题 新系统【河流水系流量评估】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题 【河流水系流量评估】多语言题解。 阅读详情

📺 B站:博主个人介绍

📘 博主书籍-京东购买链接*:Yocto项目实战教程

📘 加博主微信,进技术交流群: jerrydev


Jetson Image-based OTA:DevKit 从零跑通官方 Demo 实操指南(R36.4.x)

目标:用 NVIDIA 官方提供的 OTA tools + payload,在一块 Jetson DevKit 上完整跑通一次 image-based OTA(Host 生成 payload → 设备侧触发 → reboot 进入 recovery kernel → 更新完成)。

说明:本文重点是“跑通官方 demo”。你会看到 服务器端只在产品化时才必需;做 demo 可以先用 scp/USB/本地 HTTP 代替“服务器下载”。


在这里插入图片描述

0. 先把话说清楚:你要跑通的“Image-based OTA demo”到底是什么

Jetson 的 image-based OTA 不是 apt upgrade 那种“装几个软件包”式升级。

它的本质是:

  • 在 Host 上把目标版本 BSP 需要更新的分区镜像(bootloader/kernel/rootfs 等)打包成一个 ota_payload_package.tar.gz。
  • 在目标设备上用 nv_ota_start.sh 触发升级。
  • 设备重启后进入 recovery kernel,由 recovery 环境完成真正的分区写入与切换。

你最终得到的不是“升级了某个包”,而是“设备被升级到一套一致的 BSP 版本快照”。

这也是 image-based OTA 的工程价值:一致性更强、可控性更强、适合 BSP/分区级升级。


1. 你现在找不到 l4t_generate_ota_package.sh 的原因(最常见坑)

很多人第一次按目录去找脚本都会懵:

  • 你在 Linux_for_Tegra/ 里能看到 tools/,但找不到 tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh。

这是正常的:

✅ l4t_generate_ota_package.sh 并不一定在“裸 Driver Package”里。它来自 ota_tools_<rel>_aarch64.tbz2 这个 OTA tools 包。

也就是说:

  • 你必须先下载 ota_tools_<rel>_aarch64.tbz2
  • 然后解压到 Linux_for_Tegra 的上一级目录(让它把 tools/ota_tools/... 放进 BSP 目录)

解压完成后脚本才会出现。

快速自检:

# 在你的 Linux_for_Tegra 目录执行:
ls tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh

# 如果提示不存在,说明 OTA tools 还没解压到位

2. Demo 跑通一次 OTA,你需要准备哪些东西

2.1 你至少需要“两份 BSP”

为了生成“从旧版升级到新版”的 OTA payload,你至少需要:

  • BASE_BSP:设备当前运行的旧版本 BSP(base release)
  • TARGET_BSP:你想升级到的新版本 BSP(target release)

初学者最推荐的 demo:用 同一大版本线内的 point release(例如 R36.4.3 → R36.4.4)来跑通流程,变量更少,排错更轻松。

2.2 你需要的两个交付物(最终要放到设备侧)

  • ota_tools_<rel>_aarch64.tbz2(工具包)
  • ota_payload_package.tar.gz(分区镜像 payload)

做 demo 时:你可以先把它们拷到板子上。

产品化时:它们通常会放到你的 OTA server,由设备端 OTA client 下载。

2.3 设备侧空间要求

ota_payload_package.tar.gz 解压 + 处理需要设备侧有足够空闲空间。

经验上你至少要准备 7GB 以上(默认 rootfs 的 payload 本身常见在数 GB 级别,具体取决于你 rootfs 大小)。

2.4 你需要知道设备的 rootfs 在哪里(eMMC 还是 NVMe)

在目标设备上运行:

findmnt /
lsblk

看到 / 挂载在 /dev/nvme0n1pX,说明你是 NVMe rootfs;
看到 /dev/mmcblk0pX,说明你是 eMMC/SD rootfs。

这会影响你后面生成 payload 时是否需要 --external-device、-S 等参数。


3. 学习路线与方法(从“跑通”到“能做产品”)

这一章是本文的“升级版核心”。很多初学者会卡在两个点:

  • 只会照命令跑一次,但不知道哪些信息是关键证据、哪些变量会影响结果。
  • 不知道下一步怎么学:NVMe、A/B、UEFI Secure Boot、Disk Encryption、数据保留、自定义任务链到底怎么插进整体框架。

下面给你一套可复用的学习方法:

3.1 三层学习目标(建议按顺序完成)

第 1 层:跑通链路(Demo 级)

  • 目标:Host 能生成 payload;Device 能触发并完成升级;能验证版本变化。

  • 输出物:

    • Host 侧:payload 文件路径与大小(ota_payload_package.tar.gz)
    • Device 侧:升级前后 /etc/nv_tegra_release、uname -a、日志(成功/失败)

第 2 层:可控与可观测(工程级)

  • 目标:知道“升级过程在哪执行”“失败在哪里看”“如何复现”。

  • 输出物:

    • 关键日志打包与归档策略
    • 故障注入复现记录(比如中途重启/断电一次)
    • 关键检查点(checkpoints)列表

第 3 层:产品化框架(产品级)

  • 目标:把 OTA 从“手动脚本”变成“守护进程 + manifest + 安全校验 + 上报 + 灰度”。

  • 输出物:

    • OTA client/service 的状态机
    • manifest 设计(版本、兼容性、hash/signature、策略)
    • server 端目录结构与访问鉴权方案

3.2 四个视角帮助你“理解而不是背命令”

你学 OTA 时,建议同时从四个视角看同一个流程:

  1. 数据流(Data Flow):payload 是怎么生成、怎么传输、怎么落盘、怎么被消费的?
  2. 控制流(Control Flow):谁发起、谁切换到 recovery、谁真正写分区?
  3. 一致性(Consistency):哪些分区必须一起升级?哪些场景可以只更 bootloader / 只更 rootfs?
  4. 恢复策略(Recovery):失败后在哪里停住?如何重试?如何回滚?

只要这四个视角建立起来,后面加 Secure Boot / Encryption / NVMe / A/B 只是“多一些参数与约束”,不会把你打回原点。


3.3 学习方法:用“证据驱动”的笔记法

我建议你每跑一次 OTA,都固定保存下面这些“证据”,这样你会越来越快:

  • 设备升级前后:

    • cat /etc/nv_tegra_release
    • uname -a
    • lsblk + findmnt /(确认 rootfs 载体)
  • Host 侧:

    • 生成命令(完整参数)
    • payload 的 sha256sum 与文件大小
    • 使用的 BASE_BSP/TARGET_BSP 路径与版本
  • Device 侧日志:

    • /ota_logs/ 目录打包(失败时一定要留)
    • 如果启用 RESERVE_LOGS=true,保留 /last_ota_update_log

这样做的好处:你以后遇到任何升级异常,不是“感觉不对”,而是“有证据能定位”。


3.4 学习路线建议(按模块递进)

建议你不要一上来就把所有高级特性叠加。最稳的顺序是:

  1. 最小 Demo:内部存储 rootfs + 无 secure boot + 无加密(本文主流程)
  2. 可观测性增强:保留成功日志 + 故障注入一次
  3. NVMe rootfs:--external-device 与 -S
  4. 数据保留:nv_ota_preserve_data.sh + 文件清单
  5. 自定义任务链:nv_ota_customer.conf 的 OTA_TASKS
  6. UEFI Secure Boot:--uefi-keys/UUID/overlay 包
  7. Disk Encryption:ROOTFS_ENC=1、EKS/EKB 一致性

每加一个模块,你只需要回答一个问题:

  • 它引入了哪些新输入(参数/文件/密钥/UUID)?
  • 它改变了流程中的哪一步?(生成 payload / 触发 / recovery 任务链 / 分区写入)

4. 全局流程框架图(控制流 + 数据流)

下面这张图建议你反复看。它把“demo”和“产品化”放在同一框架里:

                   ┌────────────────────────────┐
                   │            Host            │
                   │  (build / generate payload)│
                   └──────────────┬─────────────┘
                                  │
                                  │ 生成
                                  │  - ota_payload_package.tar.gz
                                  │  - (可选) UEFI overlay 等
                                  ▼
                    ┌───────────────────────────┐
                    │       Artifacts/Repo      │
                    │  (文件落地位置/制品库)     │
                    └──────────────┬────────────┘
                                   │
                 demo: scp/USB     │     product: OTA Server/CDN
                                   ▼
               ┌────────────────────────────────────┐
               │               Device               │
               │  OTA client/service(你自己实现)   │
               │  - 下载 tools/payload              │
               │  - 校验(hash/sign/encrypt)       │
               │  - 调用 nv_ota_start.sh            │
               └──────────────┬─────────────────────┘
                              │
                              │ 触发后重启
                              ▼
               ┌────────────────────────────────────┐
               │          Recovery Kernel            │
               │  - nv_ota_run_tasks.sh 任务链       │
               │  - 写分区/切换/验证/失败处理        │
               │  - 产生 /ota_logs/                  │
               └──────────────┬─────────────────────┘
                              │
                              │ 完成后重启
                              ▼
               ┌────────────────────────────────────┐
               │          Updated System             │
               │  - 版本验证                          │
               │  - 上报结果(成功/失败/日志)        │
               └────────────────────────────────────┘

这张图里你要记住两句话:

  • 真正写分区的工作是在 Recovery Kernel 里完成的。
  • 服务器端与 OTA client 是“产品化的必需品”,但 Demo 可以先不用。

5. 一张流程图:把整个 demo 拆成 8 个动作

Host 端
  (1) 准备 BASE_BSP / TARGET_BSP
  (2) TARGET_BSP: 解压 sample rootfs + apply_binaries
  (3) 解压 ota_tools_<rel>_aarch64.tbz2 到 TARGET_BSP 上一级
  (4) 运行 l4t_generate_ota_package.sh 生成 ota_payload_package.tar.gz

传输
  (5) 把 ota_tools_<rel>_aarch64.tbz2 + ota_payload_package.tar.gz 拷到设备

Device 端
  (6) 解压 ota_tools 到 WORKDIR
  (7) 把 payload 放到 /ota/,执行 nv_ota_start.sh
  (8) reboot → recovery kernel 自动执行 OTA → 回到系统验证

4. Host 端:生成 OTA payload(一步一步照着做)

下面我用一个“最接近官方文档的写法”来讲。你可以把路径换成你自己的目录。

4.1 准备目录与变量

假设你的工作目录结构像这样:

~/ota_demo/
  ├── base_R36.4.3/Linux_for_Tegra/
  ├── target_R36.4.4/Linux_for_Tegra/
  ├── ota_tools_R36.4.4_aarch64.tbz2
  └── (样例 rootfs tbz2)

设置环境变量:

export BASE_BSP=~/ota_demo/base_R36.4.3/Linux_for_Tegra
export TARGET_BSP=~/ota_demo/target_R36.4.4/Linux_for_Tegra

注意:BASE_BSP/TARGET_BSP 要指向 Linux_for_Tegra 目录本身。

4.2 在 TARGET_BSP 准备 rootfs(sample rootfs + apply_binaries)

进入目标 BSP:

cd $TARGET_BSP

# 进入 rootfs 目录,把 sample rootfs 解压进去
cd rootfs
sudo tar xpf ../../Tegra_Linux_Sample-Root-Filesystem_<rel>_aarch64.tbz2
cd ..

# 把 NVIDIA 的二进制组件合入 rootfs
sudo ./apply_binaries.sh

如果你已经用自己的 rootfs(定制过)替换了 sample rootfs,也可以,但初学 demo 强烈建议先用 sample rootfs 跑通。

4.3 解压 OTA tools:让脚本出现在 tools/ota_tools/...

这是你现在最可能缺的步骤。

在 Linux_for_Tegra 的上一级执行解压:

cd ${TARGET_BSP}/..

# tbz2 常见写法:-j 表示 bzip2
sudo tar xjpf ota_tools_<rel>_aarch64.tbz2

解压后你应该能看到:

ls ${TARGET_BSP}/tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh

如果这一步仍然找不到,通常原因只有两类:

  1. 你解压的位置不对(没有解压到 ${TARGET_BSP}/..)
  2. 你下载的 ota_tools_<rel>_aarch64.tbz2 与目标 BSP 版本不匹配

4.4 选择正确的 <target_board>(DevKit 最常用)

官方把不同设备映射到 target_board 名称(也就是你平时 flash.sh 用的那个板级名)。

常见 Orin 系列:

  • Jetson AGX Orin DevKit:jetson-agx-orin-devkit
  • Jetson AGX Orin Industrial:jetson-agx-orin-devkit-industrial
  • Jetson Orin NX / Orin Nano(很多情况下都用):jetson-orin-nano-devkit

你可以通过以下方式辅助确认:

# Linux_for_Tegra 下有大量 *.conf
ls *.conf

# 你也可以看你曾经 flash 时用的是哪一个
# 比如 jetson-orin-nano-devkit.conf / jetson-orin-nano-devkit-nvme.conf

4.5 运行 l4t_generate_ota_package.sh 生成 payload

进入目标 BSP 根目录:

cd $TARGET_BSP

生成命令结构是:

sudo -E ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh \
  [options] <target_board> <bsp_version>
  • <bsp_version> 是“base BSP 的大版本线”,格式像 R36-4、R35-5 这种。
  • 如果你的 base 设备当前是 36.4.x,那么这里一般用 R36-4。

最小 demo(内部存储 rootfs,无加密、无 secure boot):

sudo -E ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh \
  jetson-orin-nano-devkit R36-4

说明:这个脚本默认会基于 Linux_for_Tegra/rootfs/ 生成 rootfs 镜像,再把需要更新的分区镜像都打进 payload。

生成结果在哪里?

通常会生成在:

${TARGET_BSP}/bootloader/<target_board>/ota_payload_package.tar.gz

你可以这样确认:

ls -lh ${TARGET_BSP}/bootloader/jetson-orin-nano-devkit/ota_payload_package.tar.gz

4.6(可选)如果你的 rootfs 在 NVMe:添加 --external-device 与 -S

如果你是 NVMe 启动/根文件系统在 NVMe,通常需要类似:

sudo -E ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh \
  --external-device nvme0n1 -S <rootfs_size> \
  jetson-orin-nano-devkit R36-4
  • --external-device nvme0n1 表示外置设备
  • -S 用于指定 rootfs 分区大小(具体取值与你的分区规划有关)

初学 demo:你可以先用“内部存储 rootfs”的设备跑通一次,再挑战 NVMe 场景。


5. 把文件拷到 DevKit(demo 不需要正式服务器)

你需要拷两个文件到板子上:

  1. ota_tools_<rel>_aarch64.tbz2
  2. ota_payload_package.tar.gz

最常用做法:用 scp:

# Host 上执行
scp ota_tools_R36.4.4_aarch64.tbz2 ubuntu@<JETSON_IP>:~/
scp ${TARGET_BSP}/bootloader/jetson-orin-nano-devkit/ota_payload_package.tar.gz ubuntu@<JETSON_IP>:~/

也可以用 U 盘或局域网临时 HTTP。

再强调一次:跑 demo 不需要服务器。
服务器端是“产品化 OTA”(规模化分发、鉴权、安全、灰度)才必须的。


6. 设备侧:触发 OTA(最关键的 10 分钟)

6.1 安装依赖并检查空间

在 Jetson 上:

sudo apt-get update
sudo apt-get install -y efibootmgr nvme-cli

df -h /

确认 / 有足够空闲空间(建议 7GB+)。

6.2 准备 WORKDIR 并解压 OTA tools

mkdir -p ~/ota_work
export WORKDIR=~/ota_work

cd $WORKDIR
sudo tar xjpf ~/ota_tools_<rel>_aarch64.tbz2

解压后你应该能看到:

ls $WORKDIR/Linux_for_Tegra/tools/ota_tools/version_upgrade/nv_ota_start.sh

6.3 准备 /ota/ 并放入 payload

sudo mkdir -p /ota
sudo cp ~/ota_payload_package.tar.gz /ota/

如果你启用了 UEFI secure boot,并且生成了 overlay 包,也需要一并放进去:

# 仅当你确实启用 UEFI secure boot 时
sudo cp ~/uefi_secureboot_overlay_multi_specs.tar.gz /ota/

6.4 执行 nv_ota_start.sh 并 reboot

cd $WORKDIR/Linux_for_Tegra/tools/ota_tools/version_upgrade

# 触发 OTA 预处理
sudo ./nv_ota_start.sh /ota/ota_payload_package.tar.gz

# 没报错就重启
sudo reboot

重启后通常现象:

  • 设备会进入 recovery kernel 环境
  • 屏幕可能黑一段时间/或显示不同的启动过程(这取决于平台与配置)
  • 更新完成后自动重启回系统

6.5 验证升级是否成功

回到系统后做三个验证:

  1. 查看 L4T 版本:
cat /etc/nv_tegra_release
  1. 查看内核版本:
uname -a
  1. 如果你启用了 A/B,可以看 slot 信息(不同版本工具略有差异):
# 可能存在:
nvbootctrl dump-slots-info || true
nvbootctrl get-current-slot || true

7. 你最可能遇到的 12 个问题(以及一眼能懂的处理方式)

Q1:Host 上找不到 l4t_generate_ota_package.sh

原因 99%:没解压 ota_tools 包到正确位置。

你需要在 ${TARGET_BSP}/.. 执行:

cd ${TARGET_BSP}/..
sudo tar xjpf ota_tools_<rel>_aarch64.tbz2

然后脚本才会出现在:

${TARGET_BSP}/tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh

Q2:生成 payload 很慢,像“卡住”

l4t_generate_ota_package.sh 默认会生成多 spec 的 payload(覆盖多个设备/配置),这会显著拉长时间。

思路:

  • 先确认你只需要某个 devkit 的 spec
  • 按官方建议可以通过 ota_board_specs.conf 注释掉不需要的 spec 来加速

Q3:设备侧报空间不足/解压失败

  • 检查 df -h /
  • 清理无用文件、docker 镜像、旧日志
  • 确保你把 payload 放在一个有足够空间的文件系统上

Q4:设备重启后进了 recovery shell 或更新失败

失败日志会在:

/ota_logs/

把日志打包出来最有效:

sudo tar czf ota_logs.tgz /ota_logs

Q5:成功了但日志没了

默认成功会自动删日志。

如果你想保留成功日志,需要在配置里打开 RESERVE_LOGS=true(属于 customization 话题,后面会提)。

Q6:我启用了 Secure Boot,OTA 后进 UEFI Shell

这通常说明:

  • UEFI payload / 证书链 / overlay 包处理不完整
  • 或者 boot 配置/UUID 不匹配

建议你先用“不启用 secure boot”的最小 demo 跑通,再逐层加 secure boot。

Q7:NVMe rootfs 升级不对/升级后找不到 rootfs

最常见原因:

  • Host 端生成 payload 时没有带 --external-device nvme0n1 与 -S

先跑通 internal rootfs,再来 NVMe,会更顺。

Q8:想保留用户数据怎么办

官方提供了“APP 分区文件备份/恢复”脚本:

  • nv_ota_preserve_data.sh
  • ota_backup_files_list.txt

你可以把要保留的路径列进去(相对根目录的写法)。

Q9:我用的是自定义 rootfs(不是 sample rootfs)

两条路:

  • 简单路:先把你的 rootfs 直接放到 Linux_for_Tegra/rootfs/ 再生成
  • 稍复杂:用 -o 指定 rootfs updater,用 -f 指定你的 rootfs image

初学者建议先用 sample rootfs 把链路跑通。

Q10:我只想更新 bootloader 或只想更新 rootfs

脚本支持:

  • -b:只更新 bootloader(通常在无布局变化时有意义)
  • -r:只更新 rootfs(同上)

Q11:我想做断电恢复/重试

OTA 在 recovery kernel 中执行。

如果断电重启,系统可能会回到 recovery kernel 并继续。

重试次数由 OTA_MAX_RETRY_COUNT 控制(默认 0)。

Q12:我到底需不需要服务器端

  • 跑 demo:不需要(拷贝文件即可)
  • 产品化:需要(版本管理、鉴权、安全策略、灰度、监控)

8. 从“demo”到“产品 OTA”,你还缺哪些模块

官方文档把边界说得很清楚:NVIDIA 提供“更新工具链”,但完整的 OTA 解决方案需要你补齐。

你至少要补:

  1. OTA server:存放 payload 与 tools

  2. OTA client/service(设备端守护进程):

    • 周期性检查更新
    • 下载 payload/tools
    • 校验(签名/哈希/版本白名单)
    • 触发 nv_ota_start.sh
    • 上报结果(成功/失败原因/日志)
  3. 安全策略:

    • payload 签名/加密
    • server 鉴权(mTLS/Token)
    • 防回滚策略(至少要版本 gate)
  4. 发布策略:灰度、分批、回滚

如果你希望尽快把“服务器端 + client”做起来,可以参考行业里常见的三类做法:

  • 设备管理平台型(例如把 payload 上传到某些设备管理平台,由平台分发)
  • OTA 专业平台型(例如集成专业 OTA 平台)
  • 自研极简型(Nginx + manifest + systemd service)

9. 真实世界的“全网实例”:别人是怎么把官方 OTA 做成可用方案的

下面这些内容的共同点是:

  • payload 仍然是 NVIDIA 的 ota_payload_package.tar.gz
  • 设备侧触发仍然依赖 nv_ota_start.sh
  • 差异只在“服务器与客户端”如何封装、如何安全分发与监控

你可以把它们当作“从 demo 走向产品”的参考路线:

  1. Allxon/Seeed 的 Jetson OTA 指南:强调把 OTA payload 上传到管理平台,然后平台下发到设备触发更新。
  2. Memfault 的 Jetson OTA 实践:重点在把 Jetson Linux 镜像更新接入到 Memfault 的 OTA 工作流,解决远程批量更新与可观测性。
  3. Mender 社区对 Jetson 的集成讨论:更偏工程集成(rootfs updater、golden image、与现有 OTA 框架结合)。

这些实例不等同于“官方 demo”,但很适合你理解:NVIDIA 给的是底层更新机制,生态里在其上叠加了 server/client/安全/观测。


10. 一页纸 Checklist:照着做,不容易漏

Host 端

  • 准备 BASE_BSP 与 TARGET_BSP(两份 Linux_for_Tegra)
  • TARGET_BSP:rootfs 解压 + apply_binaries.sh
  • 下载并解压 ota_tools_<rel>_aarch64.tbz2 到 ${TARGET_BSP}/..
  • 确认脚本存在:tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh
  • 选择 target_board(DevKit 常见:jetson-orin-nano-devkit 等)
  • 运行脚本生成 payload
  • 找到 payload 路径:${TARGET_BSP}/bootloader/<target_board>/ota_payload_package.tar.gz

Device 端

  • df -h / 确认空间(建议 7GB+)
  • 安装 efibootmgr、nvme-cli
  • 准备 WORKDIR,解压 ota_tools_<rel>_aarch64.tbz2
  • 准备 /ota/,放入 ota_payload_package.tar.gz
  • 执行 nv_ota_start.sh
  • reboot,等待更新完成
  • 验证:cat /etc/nv_tegra_release

11. 结语:你跑通 demo 之后,下一步最该做什么

跑通一次官方 demo 的意义是:

  • 你确认了 payload 生成链路是 OK 的(Host 工具链 + BSP 制品)
  • 你确认了 设备进入 recovery kernel 更新分区这条链路是 OK 的(执行环境与日志路径)
  • 你拿到了“失败/成功”的证据入口,后续才谈得上可靠性与产品化

为了让你的学习更系统,我建议你在跑通之后做一次“结构化复盘”:

11.1 用一个“状态机”描述设备侧 OTA(非常推荐)

把你的 OTA client(哪怕现在只是手动操作)抽象为下面 7 个状态:

IDLE
  ↓ (发现更新)
CHECK_COMPAT (机型/版本/存储形态/白名单)
  ↓
DOWNLOAD (tools + payload)
  ↓
VERIFY (hash/signature/decrypt)
  ↓
STAGE (放到 /ota/,准备 WORKDIR)
  ↓
TRIGGER (nv_ota_start.sh)
  ↓ (reboot)
RECOVERY_UPDATE (recovery kernel 中执行)
  ↓
REPORT (成功/失败/日志上传)

这样做的好处是:

  • 你以后接入 server、做灰度、做失败重试,都只是“给状态机加事件与策略”。
  • 你排障时也更容易定位:卡在哪个状态?哪一步输入不符合?

11.2 画一张“脚本调用链图”,帮助你快速定位问题

当你看到 nv_ota_start.sh 时,不要把它当成“一个脚本”。它更像是“触发器”。

你可以用下面这张简化调用链来理解:

Host:
  l4t_generate_ota_package.sh
    └─ 产出 ota_payload_package.tar.gz

Device (正常系统):
  nv_ota_start.sh
    ├─ 解包/准备/校验(按配置)
    └─ 触发进入 recovery kernel

Device (recovery kernel):
  nv_ota_run_tasks.sh
    ├─ 任务1:必要的环境/挂载/检查
    ├─ 任务2:分区写入/切换
    ├─ 任务3:验证与清理
    └─ 失败:写入 /ota_logs/ 并停留/重试

当你遇到问题时,先回答一个问题:

  • 问题发生在“正常系统”阶段,还是“recovery kernel”阶段?

如果是后者,直接抓 /ota_logs/,往往比你在正常系统里猜更有效。

11.3 下一步最推荐的学习任务(按优先级)

  1. 把成功日志也保留下来(便于对照)
  2. 做一次“可控故障注入”(中途重启/断电),观察是否能继续/如何失败
  3. 引入最简 server(例如 Nginx 静态文件)+ manifest(json)+ hash 校验
  4. 再逐步叠加:NVMe → 数据保留 → 自定义任务链 → Secure Boot → Encryption

你会发现:一旦你把“框架”搭好了,后面的高级特性都是“在框架内加约束”。


附录 A:最常用命令速查

# Host:解压 ota_tools 到 TARGET_BSP 的上一级
cd ${TARGET_BSP}/..
sudo tar xjpf ota_tools_<rel>_aarch64.tbz2

# Host:生成 payload
cd ${TARGET_BSP}
sudo -E ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh \
  jetson-orin-nano-devkit R36-4

# Device:准备并触发
sudo apt-get install -y efibootmgr nvme-cli
mkdir -p ~/ota_work && export WORKDIR=~/ota_work
cd $WORKDIR && sudo tar xjpf ~/ota_tools_<rel>_aarch64.tbz2
sudo mkdir -p /ota && sudo cp ~/ota_payload_package.tar.gz /ota/
cd $WORKDIR/Linux_for_Tegra/tools/ota_tools/version_upgrade
sudo ./nv_ota_start.sh /ota/ota_payload_package.tar.gz
sudo reboot

# 验证
cat /etc/nv_tegra_release
uname -a


📺 B站:博主个人介绍

📘 博主书籍-京东购买链接*:Yocto项目实战教程

📘 加博主微信,进技术交流群: jerrydev


MFC工具栏增加EditBox和Button 1. 在资源视图中增加EditBox, Button控件,ID分别为ID_EDIT_SEED, ID_BTN_SEED 2. 在CMainFrame中增加成员变量 CMFCToolBarEditBoxButton *m_editSeed; CMFCToolBarButton *m_btnSeed; 3. 在CMainFrame::OnCreate中创建控件 m_editSeed = new CMFCToolBarEditBoxButton(ID_EDIT_SEED, GetCmdMgr()-&. 阅读详情

相关推荐

树莓派5首次开机保姆级教程(无显示器通过VNC连接树莓派桌面)

选择 Interface Options > VNC > Yes 启用服务。2.在Windows电脑上安装VNC软件。重启树莓派:sudo reboot。3.使用VNC远程访问树莓派桌面。

qq_34184505的博客 2349

Jetson 产品级 OTA 完整方案:JetPack / Yocto + Mender 架构与落地指南

本文介绍了一套适用于NVIDIA Jetson的产品级OTA方案,重点解决实验室刷机脚本无法满足的远程更新需求。方案包含两条技术路线:基于JetPack/L4T的官方更新机制和基于Yocto的Mender方案。文章详细分析了产品级OTA的核心需求,包括安全传输、原子切换、自动回滚等关键特性,并对比了NVIDIA提供的APT和镜像级两种OTA方式。特别介绍了Mender作为完整OTA平台的架构组成,包括设备端代理、服务器管理和更新包格式,为Jetson设备提供可落地的舰队级OTA解决方案。

Interview_TC的博客 573

通过arcmap制作的第一张流域图

需要知道,识别河流依次需要填洼,流向,流量,栅格计算器,河流链接,河网分级.通过卫星图确定河流入口,在入口处画一个点,注意不要与其他河流相交。随后是进行对河流的筛选使用con函数,筛选流量大于100的河流。我们使用镶嵌工具-->镶嵌至新栅格 将两个数据合并。填洼后如图,随后进行流向的获得.使用流向工具。首先导入准备好的数据,可见两张图片并非一体。教程参考b站up:爱画地图的boney。惊醒栅格河网矢量化,进行河流分级。输入表面栅格数据,等待后如图。本次制作的是双峰县的流域图。输入流向数据,输出后如图。

pianmian1的博客 2224

Jetson镜像级OTA实操指南:从载荷生成到设备升级全流程

嵌入式系统升级是开发中的刚需,传统烧录方式耗时且风险高,OTA技术因此成为设备维护的关键能力。OTA分为包级与镜像级两种路线,包级升级适合小版本修订,而镜像级升级通过整包替换确保内核、UEFI与驱动版本一致,更适合跨版本或启动链更新。在Jetson平台的Orin DevKit上,R36.x正式提供了基于nv_ota_update的镜像级OTA支持,开发者可借助该工具实现系统镜像的生成、传输、校验与安全回滚。这一能力不仅让DevKit的版本迭代告别Recovery线刷,更为批量设备的远程运维打下了基础。本文以

weixin_29172963的博客 228

虚幻商城 Quixel 免费资产一键入库

在免费领取所有Megascans之后,我们只是有了获取 Quixel Megascans 资产的资格,但是没有入 Fab 库,本文将讲解通过脚本将 Quixel 所有资产入库 Fab。

一碗清深的博客 3265

【LLM技术全景】规模定律与模型演进:为什么模型越大越强?

规模定律性能 ∝ 参数量^N性能 ∝ 数据量^M性能 ∝ 计算量^L其中 N, M, L 是小于1的正数(通常0.05~0.15)关键观察损失与规模的关系呈幂律(不是线性,也不是对数)三个要素(参数、数据、计算)需要协调增长只增加其中一个要素,收益会边际递减规模定律(Scaling Law):1. 模型性能与参数量、数据量、计算量呈幂律关系2. Kaplan定律(2020):参数量是主要因素3. Chinchilla定律(2022):数据和参数同等重要,最优比例1:20。

专注:太空算力、AI infra、异构调度、大模型成本工程 492

Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用

由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。

2601_95893075的博客 214

【ARM CoreLink 系列 4 -- NIC-400 控制器详细介绍】

正常情况下,一个NIC的实现,可以包含一百多个master和几十个slave,每个master和每个slave都会有一些寄存器,这些寄存器可以被 programming,实际实践中就会对 AMIB 或者 ASIB 或者 IB,当它需要具有 programming的时候,给它指定一个node number。为什么指定Node Number呢?首先,从CPU的角度,它需要有一个1M对齐的地址空间,在这1M地址空间上,对每个ASIB或者AMIB这样的接口给它一个node number以后,

CodingCos的博客 5239

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 319

Simulink开发项1000例实战专栏--实例161:基于Simulink实现电动汽车电机驱动系统的建模与仿真

通过上述步骤,我们成功实现了基于Simulink的电动汽车电机驱动系统的建模与仿真。该系统能够全面评估电机驱动系统的性能,验证控制策略的有效性,并通过优化设计提高车辆的动力性和效率。引入智能预测:结合人工智能技术,实现更智能的控制策略。扩展功能:增加对多种电机类型的支持,提升系统通用性。实验验证:将仿真模型应用于实际硬件,进行实验验证,评估其在实际工况下的表现。

xiaoheshang_123的博客 187

matlab处理las点云(1)——las/laz格式解析【2024最新版】

matlab中的las/laz格式解析。博客长期更新,本文最近一次更新时间为:2024年11月9日。

点云侠的博客 8459

【JVM】对象内存布局

HotSpot JVM 中,Java 对象内存布局由对象头(12字节,含Mark Word与压缩Klass Pointer)、实例数据及对齐填充构成,总大小为8字节倍数。对象头支持锁状态动态复用,指针压缩使引用仅4字节,但堆超32GB时失效。实例字段按类型优先级重排序以减少间隙,最小对象大小为16字节。通过JOL工具可精准验证布局,理解锁机制、GC、伪共享等底层行为。

2301_79732484的博客 138

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 187

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 108

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 350

Decorator

TaskDecorator 是异步场景下"跨线程传递上下文"的标准方案,主要用于传递 MDC、用户信息、数据源路由等上下文数据,核心价值是让异步任务的日志链路不中断、业务上下文不丢失。TaskDecorator 是 Spring 提供的一个钩子接口,用于在异步任务执行前对 Runnable 进行包装,常用于跨线程传递上下文。如果你在项目中遇到具体的异步上下文传递问题,可以把代码贴出来,我帮你给出最合适的 Decorator 方案 👍。✅ 核心能力:在线程切换时,把"父线程的上下文"搬到"子线程"

wlwork66的博客 100

JDK 下载安装:装完 Java 提示「不是内部或外部命令」?环境变量没配

JDK 是写 Java 程序必须装的东西。它包含运行 Java 的虚拟机(JRE)和编译 Java 的编译器(javac)——装了它,能跑、.java文件能编译成可执行程序。免费,学习和小规模生产都不花钱。

科小怪的博客 606

数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南

Oracle 提供了ORA_ROWSCN伪列(System Change Number),记录最后修改行的 SCN,类似 PostgreSQL 的xmin。实践中通常仍使用 version 字段方案,逻辑与 MySQL 完全相同。-- Oracle:通过 ORA_ROWSCN 实现乐观锁-- 更新时比对 SCN// 自定义注解// AOP 切面@Aspect@Component@Slf4jtry {

yjc_1111的专栏 389

C++ 多态详解:作用、原理与实战用法

多态是C++面向对象的核心特性,通过虚函数实现运行期动态绑定,使同一接口在不同对象上表现出不同行为。其核心作用包括统一接口、提升可扩展性、降低耦合、支持运行时分派与批量处理。实现依赖虚函数表(vtable)和虚指针(vptr),需注意虚析构函数、对象切片等陷阱。相比编译期多态(模板),运行期多态灵活性高但有调用开销。合理结合两者,可兼顾代码的灵活性与性能,是构建可扩展、低耦合系统的关键。

2402_85743155的博客 368

java框架大全

java框架大全

qq_39326137的博客 180

SecureRandom做随机源,这个Java随机字符串工具类有3个方法

本文分享一款JDK17环境下的Java随机字符串工具类,内置3个开箱即用的方法,全部采用SecureRandom加密安全随机源,不存在弱随机、可预测、取模偏差等问题。工具类支持默认62字符集随机串、纯数字随机串、自定义字符集随机串三种生成模式,支持Unicode码点级别的字符集处理,兼容Emoji等增补字符,边界处理严格,异常信息明确,适合验证码、邀请码、盐值、随机口令、短链码等场景,源码可直接复制使用。

Java后端 | AI智能体应用实战派 | 电脑技能行家 290

Java实现批量线段相交检测(跨积判定+扫描线优化与踩坑复盘)

【代码】Java实现批量线段相交检测(跨积判定+扫描线优化与踩坑复盘)

m0_64476639的博客 305

Agent 状态栏在上下文中的具体位置

Agent状态栏以user角色消息形式追加至上下文末尾,而非修改system消息,避免破坏KVCache。此举仅为API技术实现,内容由框架自动生成,非真实用户输入,通过<agent_status>标签标识,确保模型获取最新状态且不影响缓存。该设计遵循“动态信息追加、静态信息固定”原则,实现高效、低延迟的状态传递。

lj1109053360的专栏 67

ubuntu安装hadoop系统

本文详细介绍了基于VMware克隆虚拟机搭建三节点Hadoop分布式集群的全过程:使用同一Ubuntu镜像克隆出master、worker1、worker2三台虚拟机,依次配置主机名、固定IP(如192.168.82.10/11/12)、SSH服务及免密登录,确保节点间网络互通。随后安装Java,下载配置Hadoop并分发至各节点,最终初始化启动集群,验证其存储与计算功能,实现高效的大数据环境部署。

qq_43592674的博客 279

Spring事务和事务传播机制

3. 可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同⼀事务多次查询的结果⼀致, 但是其他事务新插⼊的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.p1事务可以认为是⽗事务, 嵌套事务是⼦事务. ⽗事务出现异常, ⼦事务也会回滚, ⼦事务出现异常, 如果不进⾏处理, 也会导致⽗事务回滚.

txxzjmzlh的博客 201

RuoyiOffice 容器化落地:镜像分层、JVM 配额与三探针的联动配置

拆解 RuoyiOffice 上容器的三道坎:多阶段镜像分层、按 cgroup 配额切分 JVM 内存、startup/liveness/readiness 三探针分工,附可复制的 Dockerfile、JVM 参数与 K8s YAML。

2301_78967866的博客 299
上一篇: RK3588 声卡与 ALSA/ASoC 实战整理
下一篇: Jetson 镜像级 OTA(Image-based OTA)产品化理解与实战:从 Payload 结构到 A/B 回滚
嵌入式孙老师
博客等级 码龄7年 5686粉丝 898原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值