1. 为什么值得把整套 ROS2 开发环境塞进一枚 U 盘
手上有一套装好 ROS2 的 Ubuntu,等于随时有一间能立刻开工的机器人开发实验室。但现实往往不配合:你自己的笔记本装着 Windows 且家里不让动分区,实验室的工控机被别人占着跑仿真,比赛现场借来的机器更是碰都不敢碰。把 Ubuntu 加 ROS2 完整装进一枚 U 盘,插上开机就进系统,拔下来就是一枚普通存储盘,这套方案我断断续续用了几年,好处远比想象中多,坑也比想象中密。
先说清楚它到底是什么。这里讲的不是用 Rufus 写一个 Live 启动盘然后只做试用,也不是把 ISO 挂上去装个"体验模式",而是把 U 盘当成真正的系统盘:在它上面划分 EFI 分区、根分区,把 GRUB 引导也写进 U 盘自己的 EFI 分区,装完之后只要主板的 UEFI 能识别这个 USB 设备,系统就完全独立运行。ROS2 装在 /opt/ros 下,工作空间放在 /home 里,整套环境跟着 U 盘走,插到哪台机器上都是同一套配置、同一个工作空间,连终端历史记录都在。
1.1 三个我真正用到它的场景
第一个场景是临时借用别人的电脑。去合作方那边调一个机械臂的抓取流程,对方只给一台装着 Win11 的办公本,而且明确说不要装双系统。我掏出 U 盘,进 BIOS 把启动顺序调一下,五分钟之后ros2 topic list已经跑起来了,他们机器里的东西一个字节都没动。走的时候拔盘重启,对方完全无感。
第二个场景是多台机器共用一套环境。我自己有台式机、笔记本和一台放在实验室的小主机,三台机器硬件差异很大,如果每台都装一遍 ROS2,光是驱动和依赖的版本漂移就够折腾。把环境统一在一枚 U 盘上,台式机上编译好的工作空间,插到笔记本上直接跑,只要架构同样是 x86_64,二进制兼容没问题。代价是笔记本上如果用的是 NVIDIA 独显,驱动要单独折腾,这点后面会细说。
第三个场景是给别人演示或者教学。带一堆学员装 ROS2,最崩溃的就是每个人卡在不同的环节:有人卡在 rosdep 初始化,有人卡在源的问题,有人 Ubuntu 版本不对导致 apt 装不上 Jazzy。如果我手里有十枚装好环境的 U 盘,事情就变成"插上、开机、跟着敲命令",把三小时的安装环节压缩成三分钟。
1.2 U 盘、虚拟机、双系统、容器的各自边界
这几种方案不存在谁替代谁,关键看你怕不怕"环境被污染"和"性能被削"。虚拟机最安全,但 USB 设备直通经常出问题,接一个真实的串口传感器或者 CAN 分析仪,虚拟机里识别不到的概率不低;双系统性能最好,可你没法把它带在身上,而且误操作分区的风险实打实存在;容器轻量、迁移方便,但它依赖宿主机的内核,机器人开发里经常要改内核参数、装实时补丁、调 USB 权限,容器里做这些很别扭。
U 盘方案的位置在中间:它是完整的、可移动的、真机运行的系统。缺点也很直白——IO 性能上限受 USB 总线和 U 盘主控限制,编译大型工作空间时会明显比内置 SSD 慢。所以我的定位一直很清晰:日常开发还在主力机上,U 盘系统负责"移动、演示、应急、隔离环境"这四件事。你要是打算拿它当唯一的开发环境,后面关于写入削减和散热的那一节必须认真看。
2. 先选硬件再谈安装:U 盘的颗粒、主控与接口决定了系统能不能跑顺
大多数人失败在第一枚 U 盘上。他们随手拿了一枚几年买手机送的赠品盘,容量 16G,插上去开始装系统,装到一半提示空间不足;或者好不容易装完,apt update卡了十分钟,风扇狂转,最后dpkg报错。问题不在 Ubuntu,也不在 ROS2,在于那枚盘根本不适合当系统盘用。
U 盘的本质是一块闪存加一个主控。当系统盘用,考验的是三件事:4K 随机读写速度、持续写入时的速度稳定性、以及读写寿命。厂商标的"读取 150MB/s"是顺序大文件的速度,跟你编译代码时的体验几乎无关。系统启动、加载动态库、读写小文件、日志写入,全是 4K 随机操作,而这恰恰是廉价 U 盘最弱的地方——它们的 4K 随机写入可能只有 0.5MB/s,甚至更低。
2.1 普通 U 盘为什么会在 apt install 时卡到怀疑人生
我给一个具体数字对比。一枚百元以内的普通 USB 3.0 U 盘,顺序读大概 100~150MB/s,看似不错,但 4K 随机写经常在 1MB/s 上下,4K 随机读也就 5~10MB/s。而一块普通的 SATA SSD,4K 随机读写都在 30~60MB/s 量级,NVMe 更是几百 MB/s。
apt install一个软件包,背后是解压 tar、写入大量小文件、更新数据库、修改权限,全是随机小块写。在普通 U 盘上,这个过程会被放大几十倍。我实测过,同一个ros-dev-tools依赖组,在固态 U 盘上装完大概两分半,在普通赠品盘上跑了将近十八分钟,而且中间系统几乎卡死,鼠标都不太动。
更麻烦的是"速度悬崖"。很多 U 盘的主控带一小块 SLC 缓存,前几百兆到几个 G 的写入飞快,缓存用完之后掉速到十几 MB/s。安装系统恰恰是持续几十个 G 的写入,几乎必然触发掉速。所以判断一枚盘能不能用,别看它标的最大读取速度,去看有没有"sustained write"或者"缓外速度"这类指标。
2.2 接口、颗粒、容量和预算的实际对照
下面这张表是我这几年用过的几类盘的实际体感,不是跑分,是"装 ROS2 顺不顺"的口径:
| 类型 | 4K 随机写体感 | 装完 ROS2 后编译小工程 | 是否推荐当系统盘 |
|---|---|---|---|
| 赠品 U 盘(USB 3.0,无品牌) | 极慢,apt 卡顿明显 | 基本受不了 | 不推荐 |
| 主流品牌 U 盘 64G(USB 3.2 Gen1) | 慢,但可忍受 | 十分钟级别的编译能忍 | 应急可用 |
| 固态 U 盘 / USB 3.2 Gen2 移动固态 | 接近 SATA SSD | 顺畅,两三个包同时编译没问题 | 推荐 |
| M.2 硬盘盒 + NVMe SSD | 最快,接近内置盘 | 几乎无感 | 最推荐 |
容量上,我的建议是不低于 128G,最好 256G。算一笔账:Ubuntu 系统本体加常用软件大概 20~25G,完整 ROS2 桌面版加各种工具再吃 5~8G,一个像样点的机器人工作空间(含 Gazebo 模型、导航包、编译产物)轻松又是 20G 起,再加点数据、日志、几个 Python 环境,64G 盘装完就快满了。系统盘留 20% 以上的空闲空间对闪存寿命和性能都有好处,所以预算够的话直接上 256G。
接口方面,只要主板支持,优先用 USB 3.2 Gen2(10Gbps)或者 Type-C 口。有个容易忽略的点:很多机器的前置 Type-A 口走的是内部延长线,供电和信号质量都不如后置直连主板的接口。我遇到过同一枚盘,前置口启动三次里失败一次,后置口稳定得很。
2.3 散热与供电:看不见的掉盘原因
这是最隐蔽的一类故障。系统用着用着突然卡住,然后dmesg里出现USB disconnect或者一堆I/O error,接着挂载变成只读。多数人第一反应是系统坏了,其实是盘掉线了。
原因通常有两个。一是供电不足,尤其是通过 USB Hub 或者前置口取电,加上 NVMe 硬盘盒这类功耗偏高的设备,瞬时电流不够就断开重连。二是过热,金属外壳的固态 U 盘连续写入十几分钟,壳体温到烫手,主控降频甚至触发保护。我的做法是:不用无源 Hub,尽量直插后置口;长时间编译时把盘放在不挡风的位置,别贴着笔记本底座;如果盘是金属壳,散热本身反而是好事。
提示:安装前先做一次"折磨测试"。往盘上连续写 20G 的随机数据,看会不会中途掉速到几 MB/s,或者干脆断开。这一步花二十分钟,能省掉后面两小时的重装。
3. 从 ISO 到可启动 U 盘:分区规划与引导落点的一次性决定
硬件过了关,接下来的核心问题是:到底怎么把系统"装"进去。这一步有两类做法,很多人混在一起搞,结果做出来的是个重启就丢数据的体验盘。
第一类是用 Rufus、Ventoy、balenaEtcher 这类工具把 ISO 直接写进 U 盘。Rufus 在 Windows 下用得最多,写完之后盘上是一个只读的启动环境,进系统可以试用,但你做的任何修改重启就没了。它当然也能带持久化分区,Ventoy 支持建一个 casper-rw 存放改动,但持久化区域本质上是个覆盖层,性能差、容量受限,不适合装 ROS2 这种动不动几个 G 的依赖。
第二类是用 U 盘当真实磁盘,跑完整的安装流程。你需要先用 Rufus 做一枚安装盘(或者用另一枚盘),然后从安装盘启动,把 Ubuntu 装到目标 U 盘上。这才是本文说的方案。做启动盘的工具有不少选择,Windows 下 Rufus 用得顺手,Linux 下直接dd也行,但dd要格外小心目标设备名,写错就是清掉你的硬盘。
3.1 手动分区:EFI、根分区、swap 该怎么切
安装到"安装类型"那一步,一定要选"其他选项"(Something else),别用"清除整个磁盘并安装"。自动分区会把引导写到它认为的第一块盘上,那个"第一块盘"很可能是你的内置硬盘。
手动分区的方案我一般这么切(以 256G 盘为例):
| 挂载点 | 大小 | 文件系统 | 说明 |
|---|---|---|---|
| /boot/efi | 512M~1G | FAT32 | 必须标记为 EFI 系统分区 |
| / | 剩余全部(留 8G) | ext4 | 系统与工作空间都在这 |
| swap | 8G(可选) | swap | 内存够大可以不要,或用 zram |
关于 swap,我要多说一句。U 盘上频繁 swap 会带来大量随机写入,既拖慢系统又消耗寿命。如果机器内存有 16G 以上,我倾向于不建独立 swap 分区,改用 zram(内存压缩块设备)顶一下,实在要交换也只在小内存机器上建。另外,ext4 的日志(journal)本身也会持续写盘,后面第 6 节会讲怎么削减。
挂载点设置完之后,"安装启动引导器的设备"这一栏是整篇最关键的一个下拉框。
3.2 引导装在哪里:写错这一步会覆盖本机引导
很多人装完 U 盘系统之后,拔掉 U 盘重启,发现本机进不去 Windows 了,直接跳到一个黑底白字的 grub 提示符。原因就是安装时把 GRUB 写到了本机硬盘的 EFI 分区,而 GRUB 的配置文件在 U 盘上——U 盘一拔,本机引导就指向了一个不存在的位置。
正确做法是:把"安装启动引导器的设备"明确选成你那个 U 盘对应的设备,通常是/dev/sdb、/dev/sdc这种,不要选/dev/sda,也不要选分区号(选设备整体,不选/dev/sdb1)。同时确认你挂载的 EFI 分区是 U 盘上那个新建的 FAT32 分区,而不是本机硬盘上已有的那个 100M~500M 的 EFI 分区。
如果已经手滑覆盖了本机引导,也别慌。进主板 UEFI 的启动项列表,通常还能看到 Windows Boot Manager 这一项,把它调到首位就能进系统;进不去的话,用 Windows 安装 U 盘跑一次启动修复,或者用 U 盘上的 Ubuntu Live 环境挂载本机 EFI 分区,把被覆盖的EFI/Microsoft目录恢复回来。
3.3 Secure Boot 与戴尔等品牌机的 BIOS 设置
先说 Secure Boot。它本身是好事,防止未签名的引导程序被加载。但 Ubuntu 的 GRUB 是签过名的,大多数情况下开启也能正常启动。真正的麻烦出在第三方内核模块上,比如 NVIDIA 显卡驱动、某些无线网卡驱动,它们没签名,Secure Boot 开着就加载不了。这时候有两条路:一是在 BIOS 里关掉 Secure Boot(简单,但如果这台机器不是你的,可能不允许改);二是用mokutil走 MOK 注册流程,给驱动签一个本机信任的密钥,开机时会在蓝色界面上要求你确认一次。后面第 4 节会讲具体操作。
再说各家机器的设置入口。不同品牌的按键和菜单名称差别很大,我把常见的列一下:
| 品牌 | 进入设置 | 启动菜单 | 关键项名称 |
|---|---|---|---|
| 戴尔 | F2 | F12 | Boot Sequence、Secure Boot、SATA Operation |
| 联想 | F1 或 Fn+F2 | F12 | Boot Mode、USB Legacy |
| 惠普 | F10 | F9 | Legacy Support、Secure Boot |
| 华硕 | Del 或 F2 | Esc | CSM、Secure Boot Control |
| 微星 | Del | F11 | UEFI/Legacy、Fast Boot |
戴尔的机器我要单独提醒一句:它的"Boot Sequence"里,U 盘有时不在列表里,需要在启动时按 F12 从一次性启动菜单里选。如果还是看不到,去检查"USB Configuration"里有没有把 USB 启动打开,以及"Fast Boot"是否把它跳过了。
4. 首启之后的加固:换源、驱动、输入法与远程连接
系统装完第一次进桌面,心情通常很好,但接下来的两个小时决定这套环境能不能真的用来干活。
4.1 软件源与更新:先别急着大升级
第一件事是换源。国内环境下默认源拉包的体验很一般,换成清华、中科大或者阿里云的镜像会舒服很多。Ubuntu 24.04 用的是新的 deb822 格式,源文件在/etc/apt/sources.list.d/ubuntu.sources,格式和老的sources.list不一样,直接照抄旧教程会踩坑。改完之后跑一次sudo apt update,确认没有报 GPG 或者 404 错误,再决定要不要升级。
这里有个我踩过的坑:装完系统不要立刻apt full-upgrade。刚装好的内核和驱动是配套的,一升级内核,NVIDIA 驱动、无线网卡驱动都可能跟着出问题,尤其是 U 盘系统依赖 USB 存储驱动,内核一动有概率起不来。我的习惯是先跑一段时间确认稳定,再单独升级内核,而且升级前一定做好镜像备份(第 6 节会讲)。
4.2 显卡驱动与 Secure Boot 签名
如果这台机器是 NVIDIA 独显,装驱动这一步绕不开。Ubuntu 自带的"附加驱动"面板(software-properties-gtk的最后一页)里能选版本,我一般避开server系列,选带-open或者普通版本,跟 ROS2 里的 Gazebo、RViz2 兼容性更好。命令行的话:
ubuntu-drivers devices sudo apt install nvidia-driver-550 sudo reboot如果 Secure Boot 是开着的,装完之后开机可能会跳出一个蓝色界面要求你设置密码并注册 MOK,跟着提示走完重启即可。要是驱动装完nvidia-smi报"couldn't communicate with the NVIDIA driver",八成是 DKMS 模块没编译成功,检查dkms status和内核头文件是否装全。
还有一个 U 盘系统特有的小问题:换机器之后驱动不匹配。你在 NVIDIA 机器上装好驱动,插到 AMD 或者纯核显的机器上,系统一般还能进(会退回开源驱动或者软件渲染),但反过来从核显机器换到 NVIDIA 机器,第一次开机可能进不了图形界面。临时办法是在 GRUB 菜单里按e编辑启动参数,加个nomodeset先进系统,再装驱动。
4.3 中文输入法与必要的桌面配置
输入法这块,Fcitx5 是现在最省心的方案,比老的 fcitx4 稳定得多。装完记得做三件事:把 Fcitx5 设成默认输入法框架(im-config里选),配置环境变量(GTK_IM_MODULE、QT_IM_MODULE、XMODIFIERS),以及把 Fcitx5 加进开机自启。第三点最容易漏,漏了的结果是每次开机都要手动启动一次输入法,终端里还经常切不出中文。
sudo apt install fcitx5 fcitx5-chinese-addons fcitx5-frontend-gtk4 fcitx5-frontend-qt5喜欢用搜狗输入法的也可以装,但要注意它依赖特定的 fcitx 版本,跟 Fcitx5 有时会打架,U 盘系统上我更倾向用自带的拼音,双击安装包少、依赖干净。切不出中文的重灾区是终端,因为终端模拟器的QT_IM_MODULE往往没生效,检查一下/etc/environment里那几个变量是不是按 Fcitx5 的要求写对了。
4.4 SSH 与共享目录:让 U 盘系统融进日常工作流
装完系统我第一件事是开 SSH:
sudo apt install openssh-server sudo systemctl enable --now ssh ip addr show | grep inet这样即使 U 盘系统没接显示器,也能从另一台机器上连过去干活。注意 U 盘系统换网络环境之后 IP 会变,我一般给路由器上配个静态租约,或者干脆用主机名ssh 用户名@ubuntu-usb.local(需要装 avahi-daemon)。
共享数据我用两条路。临时传文件用python3 -m http.server起个临时服务,或者用scp;长期共用的大数据集(比如点云、地图、模型文件)我单独放一枚普通的移动硬盘上,用fstab挂载,注意用 UUID 而不是设备名,因为 U 盘系统不同机器上设备名会变,/dev/sdb1今天是对的,明天可能是/dev/sdc1,用设备名挂载会导致开机进不了系统。
5. ROS2 落地:版本匹配、一键脚本与 rosdep 排错
准备工作做完,终于到 ROS2 了。这一节我按"最容易出错"的顺序来排。
5.1 版本对照:选错版本,后面全是无效劳动
ROS2 的发行版和 Ubuntu 版本是强绑定的,装错了 apt 直接告诉你"找不到包"。当前常见的对应关系:
| ROS2 版本 | 对应 Ubuntu | 支持状态 |
|---|---|---|
| Humble Hawksbill | 22.04 LTS | LTS,生态最全,长期推荐 |
| Jazzy Jalisco | 24.04 LTS | LTS,较新,包逐步补齐 |
| Kilted Kaiju | 24.04 LTS | 较新,非 LTS |
所以如果你打算用 24.04,那就装 Jazzy;如果你更看重生态完整度和网上教程的覆盖度,22.04 + Humble 依然是最稳的组合。我自己的 U 盘系统用的是 24.04 + Jazzy,主要原因是新机器上的网卡、显卡驱动在 24.04 上支持更好,而 Jazzy 的常用包(导航、MoveIt、RViz2)现在都齐了。
有个坑要提前说:别在同一个系统上装两个 ROS2 发行版然后同时 source。两个版本的setup.bash会互相覆盖环境变量,出现"包能找到但跑起来行为诡异"的情况。要共存就分终端 source,或者老老实实一台系统一个版本。
5.2 一键脚本和手动 apt:什么时候用哪个
社区里流传很广的"鱼香 ROS 一键安装脚本",确实省事,尤其对刚接触 ROS2 的人友好,它会帮你处理源、密钥、依赖、环境变量这些琐碎环节。但它有两个前提:一是要有相对稳定的网络访问,脚本里包含不少从外网拉资源的过程;二是它对系统的假设是标准的 Ubuntu,你如果在 U 盘系统上做过比较激进的分区或者精简,脚本可能在某个环节静默失败,日志又不明显。
我的建议是:第一次装用一键脚本,但装完一定手动验证。验证方法很简单:
source /opt/ros/jazzy/setup.bash ros2 run demo_nodes_cpp talker另开一个终端跑:
source /opt/ros/jazzy/setup.bash ros2 run demo_nodes_py listener看到 listener 里刷出I heard: [Hello World: N],环境就是通的。如果脚本报错,就转手动安装,官方的 apt 流程其实也就五六步,把源加上、密钥装上、apt install ros-jazzy-desktop就完事,过程比脚本更透明。
5.3 rosdep 初始化卡住的原因和绕法
rosdep是 ROS2 装系统依赖的工具,几乎每个工作空间的colcon build之前都会用到。它出问题一般出在sudo rosdep init这一步,典型的报错是网络请求超时。原因是它要从一个外网地址拉默认源列表。
稳妥的绕法是手动创建那个文件:
sudo mkdir -p /etc/ros/rosdep/sources.list.d sudo tee /etc/ros/rosdep/sources.list.d/20-default.list << 'EOF' yaml https://mirrors.tuna.tsinghua.edu.cn/rosdistro/rosdep/osx-homebrew.yaml osx yaml https://mirrors.tuna.tsinghua.edu.cn/rosdistro/rosdep/base.yaml yaml https://mirrors.tuna.tsinghua.edu.cn/rosdistro/rosdep/python.yaml yaml https://mirrors.tuna.tsinghua.edu.cn/rosdistro/rosdep/ruby.yaml gbpdistro https://mirrors.tuna.tsinghua.edu.cn/rosdistro/releases/fuerte.yaml fuerte EOF然后rosdep update。这里的关键是把上游地址换成能稳定访问的镜像,而不是反复重试。rosdep update之后如果还报"找不到某个 key",多半是本地缓存目录权限不对,~/.ros/rosdep删掉重跑一次基本能好。
注意:
rosdep init只需要执行一次,重复执行会提示文件已存在。如果你是从别人的 U 盘系统克隆过来的,这个文件通常已经存在,直接rosdep update就行,别去重复 init。
5.4 工作空间、环境变量与 RViz2 冒烟测试
标准的工作空间流程没什么可跳过的:
source /opt/ros/jazzy/setup.bash mkdir -p ~/ros2_ws/src && cd ~/ros2_ws colcon build --symlink-install source install/setup.bash--symlink-install在 U 盘系统上我强烈建议加上。它的意思是用符号链接代替复制,Python 包改完代码不用重新 build,而且大幅减少写入量——这对闪存寿命是实打实的帮助。代价是某些情况下链接目标被移动会失效,但日常开发利大于弊。
环境变量别忘了写进~/.bashrc,否则每开一个终端都要 source 一次。但要注意顺序:先 source/opt/ros/jazzy/setup.bash,再 source 工作空间的install/setup.bash,反过来会导致工作空间里的包被系统包覆盖。
最后跑一次图形化的验证。RViz2 是 ROS2 里最常用的可视化工具,能起来基本说明图形栈和 ROS2 都正常:
rviz2如果 RViz2 启动后是黑屏或者直接崩,八成是显卡驱动的问题,先在终端里看看有没有 OpenGL 相关报错,NVIDIA 机器上试试__NV_PRIME_RENDER_OFFLOAD=1 rviz2。Intel 核显通常没这个问题。跑通 RViz2 这一步挺重要,因为后面做导航、建图、可视化点云都靠它,早点把驱动问题暴露出来,比在项目中期崩掉要好。
6. 延长 U 盘寿命的写入削减策略
闪存的写入寿命是有限次的,虽然现代主控有磨损均衡,但一个持续写日志、持续 swap、持续索引的系统盘,寿命消耗会比你想的快。这一节讲的全是"少写一点"的招,对性能也有正面作用。
6.1 noatime、日志与 tmpfs
第一招是挂载参数。ext4 默认会给每个被读取的文件更新访问时间(atime),这在系统盘上纯属浪费写入。改/etc/fstab:
UUID=xxxx-xxxx / ext4 defaults,noatime,commit=60,errors=remount-ro 0 1noatime关掉访问时间更新,commit=60把日志提交间隔从默认 5 秒拉到 60 秒,也就是把零散写入攒起来一次写。这两个参数组合起来,日常使用下的写入量能降不少。代价是异常断电时可能丢最后 60 秒的数据——对开发环境来说完全可接受。
第二招是把高频写入的目录放到内存里(tmpfs)。/tmp在现代 Ubuntu 上默认已经是 tmpfs 了,/var/log也可以考虑。但/var/log要谨慎:它的内容重启就没了,出问题时你会没有日志可查。我的折中做法是不动/var/log,只是限制 journal 大小:
sudo journalctl --vacuum-size=200M sudo sed -i 's/#SystemMaxUse=.*/SystemMaxUse=200M/' /etc/systemd/journald.conf这样日志最多占 200M,不会无限增长。
6.2 swap 放哪里:一个容易被忽略的性能陷阱
前面提过不建独立 swap 分区。如果不建,但系统又需要交换怎么办?两个方案。
一是用 zram,把一部分内存压缩当交换区用:
sudo apt install zram-tools # 在 /etc/default/zramswap 里设置 PERCENT=25 之类 sudo systemctl restart zramswapzram 的交换发生在内存里,零闪存写入,压缩比通常能有 2:1 到 3:1,对 8G 内存的机器提升明显。
二是如果非要落盘,把 swap 文件放到 U 盘的根分区上,并调低vm.swappiness(比如设成 10),让内核尽量不交换。反过来,最糟的做法是把 swap 放在另一枚慢速 U 盘或者 SD 卡上,那会拖垮整个系统的响应。
6.3 备份与迁移:dd 镜像和 rsync 两条路
U 盘系统最大的好处之一是备份极其方便。整盘镜像:
sudo dd if=/dev/sdb of=/data/ubuntu-usb-$(date +%F).img bs=4M status=progress conv=fsync注意几个点。if是 U 盘设备(是整个设备,不是分区),写错会毁数据,执行前一定用lsblk确认。生成的镜像大小等于 U 盘容量,256G 盘就是 256G 文件,用gzip压缩后一般能到 40~60G。恢复的时候反过来dd if=xxx.img of=/dev/sdb,目标盘容量必须大于等于原来那枚。
dd适合"整盘克隆",但如果你只想备份工作空间和配置,rsync更合适:
rsync -aAXH --delete --info=progress2 /home/user/ros2_ws/ /data/backup/ros2_ws/-aAXH保留权限、扩展属性、硬链接,这样恢复出来的工作空间权限不会乱。我一般两种都用:每两周做一次dd全盘镜像,每天用rsync同步工作空间。真出事的时候,从rsync目录恢复代码只要几分钟。
7. 几个真实的翻车现场和修复思路
前面讲的多是"应该怎么做",这一节讲"做错了会怎样",因为我自己全踩过。
7.1 拔盘启动后进了 grub rescue
现象是拔掉 U 盘重启,屏幕停在grub rescue>提示符。原因前面说过,引导写到了本机 EFI 分区,而 GRUB 的/boot/grub在 U 盘上。临时修复:进 UEFI 启动菜单选 Windows Boot Manager,或者用安装盘跑boot-repair。根治方法是在本机 EFI 分区里保留一个能独立引导的 Windows 引导项,然后重新安装 U 盘系统的 GRUB,位置明确选 U 盘设备。
排查思路值得记一下:不要一上来就重装系统,先用 Live 环境挂载两个 EFI 分区对比,看EFI/ubuntu/grub.cfg到底在哪个分区上,就知道引导被写到哪去了。
7.2 时间错乱:Ubuntu 和 Windows 差八小时
如果你偶尔用同一枚 U 盘启动不同机器,或者和其他系统混用,很可能遇到时间差 8 小时的问题。根因是 Linux 默认把硬件时钟当成 UTC 存储,Windows 当成当地时间存储。两种改法,改 Linux 这边:
timedatectl set-local-rtc 1 --adjust-system-clock或者改 Windows 那边(改注册表让 Windows 也认 UTC)。我一般改 Linux 这边,因为 U 盘系统是我这边可控的。但要注意,如果 U 盘系统还要和别的 Linux 服务器共用时间同步,改之前先确认 NTP 服务状态,否则时间会来回跳。
7.3 编译到一半掉盘,挂载变只读
最气人的一种。跑colcon build跑了一半,突然一堆 I/O error,然后整个根分区变成只读,什么都存不下去。dmesg | tail里通常能看到usb 2-1: reset SuperSpeed USB device反复出现,或者干脆device descriptor read error。
排查顺序我总结成了三步:先换接口,直插后置 USB 口,别用 Hub;再换线,有些 Type-C 线只支持充电不支持高速数据;最后摸一下盘的温度,烫手就加散热。如果换接口换机器都不行,那就是盘本身主控有热保护或者已经到寿命了,尽早把数据rsync出来换盘。
还有一种"假掉盘":文件系统损坏而不是硬件断开。这时候dmesg里会写EXT4-fs error。可以在 Live 环境里跑一次sudo fsck -f /dev/sdb2修复,但修完一定要第一时间备份,出现这类错误说明闪存已经出现坏块了。
7.4 换机器后连不上网或者进不了桌面
U 盘系统换主机,网卡型号变了,/etc/netplan里如果写死了旧的网卡名(比如enp3s0),新机器上可能就叫enp4s0,于是网络起不来。解决思路是把配置里的网卡名换成匹配规则(match: name: en*),或者干脆用 NetworkManager 管理,别在 netplan 里写死。
进不了桌面通常是显卡驱动的事,前面提过nomodeset的应急做法。更彻底一点的做法是在 GRUB 里保留两个启动项,一个正常启动,一个带nomodeset,换机器的时候按需选。GRUB 的自定义启动项写在/etc/grub.d/40_custom里,改完跑sudo update-grub。
最后分享几个我自己维护这套 U 盘系统的小习惯。一是给它起个有日期的标签,比如UBUNTU-ROS2-2025Q1,手上有几枚盘的时候不会搞混,e2label或者 GParted 都能改。二是每次做重大变更之前先 dd 一份镜像,尤其是升级内核、更换显卡驱动之前,这两类操作最容易把系统搞成开不了机,有镜像就能二十分钟回滚。三是别把这枚盘当唯一的数据存放地,它本质上还是消费级闪存,坏块出现的概率比企业级 SSD 高得多,工作空间每天 rsync 一遍,出问题的时候你会庆幸自己多花了那三分钟。