前几天有位做嵌入式的朋友找我,说他手上一个 2016 年的老项目要重新编译,代码里用的几个库对 glibc 版本卡得死死的,在现在的新系统上一编译就报符号找不到。折腾了两天,最后的解法朴素得有点反直觉——回到 Ubuntu 14.04.4 上去跑。于是就有了这次在 Windows 上用 VMware 装 Ubuntu 14.04.4 的完整过程。这类需求其实不少见:老项目的兼容性回归、特定版本工具链的复现、教学演示环境、遗留系统的镜像验证,都会撞上"只能装老系统"这道墙。这篇就按我实际操作的顺序,把虚拟机参数怎么定、安装时哪几个选项不能碰、装完之后哪几件事必须做,一条条摊开讲,新手照着抄能跑通,老手能直接从里面挑自己需要的配置细节。
1. 先把"为什么装这个版本"想明白
1.1 14.04.4 的版本定位与它的技术坐标
Ubuntu 14.04.4 LTS 是 14.04 这条长期支持线上的第四个点版本,2016 年 2 月发布。它的技术坐标很重要,因为这个坐标决定了它能干什么、不能干什么。点版本的核心变化在硬件支持栈(HWE),14.04.4 搭载的是来自 15.10 的 Linux 4.2 内核和配套的 X 服务栈,而 14.04.3 是 3.19,14.04.5 才升到 4.4。用户态这边则基本冻结在初始版本:glibc 2.19、GCC 4.8.4、Python 3.4.3、Unity 7 桌面、Upstart 作为 init 系统(不是 systemd,这是和 16.04 之后最大的体感差异之一)。
这几个数字放在一起意味着什么?如果你的老代码依赖 glibc 2.19 的符号版本,或者用了 4.8 系列编译器才有的行为特性,那么 16.04 的 glibc 2.23 和 GCC 5.4 就可能让编译产物在链接阶段直接炸掉。反过来,如果你需要 systemd 的 unit 文件、需要 cgroup v2、需要新内核的 eBPF 特性,那 14.04 就完全不是目标环境了,硬装上去只是给自己找麻烦。
还有一个必须说清楚的事实:14.04 这条线的标准支持在 2019 年 4 月就已经结束,之后转入扩展维护阶段,普通软件源早已不再更新,官方归档也已经挪到了独立的归档站点。所以装它的姿势和装 20.04、22.04 完全不同——不是你装完 apt-get update 就能一路顺畅,源地址得手动改,安全更新更是不用指望。我个人的原则很简单:14.04.4 只作为离线或隔离环境下的兼容性验证靶机使用,不承载任何对外服务,不存放真实业务数据,用完随时销毁快照。这个前提想清楚了,后面所有配置才有意义。
1.2 和 16.04、18.04、22.04 横向对比:到底该选哪一版
很多人上来就问"我要兼容老代码,装哪个版本合适"。与其凭感觉选,不如把关键指标摊成一张表对着自己的需求勾。
| 对比项 | 14.04.4 | 16.04 | 18.04 | 22.04 |
|---|---|---|---|---|
| 内核版本 | 4.2(HWE) | 4.4 | 4.15 | 5.15 |
| glibc | 2.19 | 2.23 | 2.27 | 2.35 |
| GCC 默认 | 4.8.4 | 5.4 | 7.5 | 11.2 |
| init 系统 | Upstart | systemd | systemd | systemd |
| Python 默认 | 3.4 | 3.5 | 3.6 | 3.10 |
| 标准支持状态 | 已结束 | 已结束 | 已结束 | 进行中 |
| 归档源是否需手动改 | 必须 | 必须 | 必须 | 不需要 |
| 典型使用场景 | 老工具链复现、教学演示 | 过渡期项目 | 中期项目 | 新项目主力 |
这张表里最容易被忽略的是 init 系统那一行。14.04 用的是 Upstart,服务管理靠service xxx start和/etc/init/*.conf,而不是systemctl。如果你从网上抄了一段systemctl enable的命令往 14.04 上贴,它会直接告诉你 command not found。我第一次踩这个坑的时候愣了半天,以为是软件没装全,后来才反应过来是年代差异。
选版本的逻辑我总结成一句话:跟着你代码的构建脚本走,而不是跟着你的喜好走。翻一翻老项目里的 CI 配置、Dockerfile、README 里写的环境要求,里面通常会明确写着"Ubuntu 14.04 + gcc 4.8"这类信息,那就是标准答案,不用猜。
1.3 虚拟机方案和物理机方案的取舍
有人会问,为什么不直接找台旧机器装物理机?我的答案很直接:除非你要测的是显卡驱动、特定的 PCI 设备、或者是需要真实硬件中断时序的性能测试,否则虚拟机方案在绝大多数场景下都更划算。
虚拟机的好处是可以把整个环境"冻结"成一个文件夹。装好、配好、打好快照,复制一份出来就是一台一模一样的新机器,几十秒的事。物理机你要重装一遍系统、重新配一遍环境,半天就过去了。而且虚拟机有快照,操作失误了回滚只要几秒钟,物理机回滚就得重装。坏处当然也有:嵌套虚拟化性能损耗、USB 设备直通偶尔抽风、3D 加速形同虚设。但对于"编译老代码"这个目标来说,这些都不是问题。
我自己的做法是给每个老项目单独建一个虚拟机文件夹,命名带上项目代号和系统版本,比如projA-u1404,所有文件放在同一个非系统盘目录下。这样三个月后再回来,双击.vmx文件就能直接开工,不用回忆当初装了什么。
2. 装之前的资源盘点与参数预算
2.1 宿主机侧必须先确认的四件事
动手创建虚拟机之前,有四件事必须先确认,否则大概率会在中途卡住,而且报错信息往往指向不明,让人误以为是安装镜像坏了。
第一件是 CPU 虚拟化是否开启。打开任务管理器,切到"性能"标签,点左侧的 CPU,右下角会显示"虚拟化:已启用 / 已禁用"。如果是已禁用,需要重启进 BIOS(或 UEFI 设置),找到 Intel VT-x 或 AMD-V 选项打开。有些品牌机的 BIOS 里这个选项藏得比较深,在 Advanced → CPU Configuration 下面,名字可能叫 Intel Virtualization Technology。
第二件是和 Windows 自带虚拟化平台的冲突问题。Windows 10/11 上如果启用了 WSL2、Docker Desktop、Windows 沙盒、内存完整性保护这几项中的任意一个,底层的 Hyper-V 平台就会被占用。较老版本的虚拟机软件会直接弹窗提示"与 Hyper-V 不兼容,需要移除 Hyper-V 角色后才能运行",然后拒绝启动。较新版本通过 Windows Hypervisor Platform 接口可以和 Hyper-V 共存,但运行性能会有一定下降。处理方式有两条路:要么在"启用或关闭 Windows 功能"里关掉 Hyper-V 相关项,然后用管理员权限的命令行执行bcdedit /set hypervisorlaunchtype off并重启;要么升级虚拟机软件到支持共存的版本,接受性能折损。
注意:关闭 Hyper-V 会影响 WSL2 和 Docker Desktop 的正常使用,如果你日常还要用这些工具,建议采用共存方案,别为了一个老系统的虚拟机把日常工作流拆了。
第三件是磁盘空间预算。这个后面单独算。第四件是虚拟机的存放路径。这一条我吃过亏:曾经把虚拟机文件夹放在 OneDrive 同步目录里,结果同步客户端在后台不断扫描几十 GB 的虚拟磁盘文件,CPU 占用飙到 30%,虚拟机里的编译速度直接砍半。正确做法是放在本地物理盘的非系统分区,路径全程用英文,不要有空格和中文。
2.2 内存和 CPU 核心数的分配公式
虚拟机内存给多少,是新手最容易拍脑袋决定的一项。给太少系统卡成幻灯片,给太多宿主机自己开始换页。我用的经验公式是这样的:
- 虚拟机内存 = 宿主机物理内存 × 25%,向上取偶数,上限 8 GB,下限 2 GB
- 虚拟机核心数 = 物理核心数 ÷ 2,向上取整,最小 1,最大 4
拿常见的 16 GB 内存、8 核 16 线程的机器举例:虚拟机内存给 4 GB,核心数给 4。这个配置跑 14.04 的 Unity 桌面已经相当流畅了,编译中等规模的 C 项目也够看。如果是 8 GB 内存的笔记本,虚拟机给 2 GB,核心数给 2,这时候桌面会略有迟滞,但做纯命令行操作完全没问题,可以考虑安装时选最小化安装。
这里有个细节值得说:14.04 桌面版的安装程序本身要求至少 1.5 GB 内存才能启动图形界面。如果你给的低于这个数,它会拒绝进图形安装器,或者进去之后直接黑屏。所以 2 GB 是硬下限,别再往下压了。
还有一个坑是"内存过量分配"。虚拟机软件允许你给虚拟机分配超过物理内存的容量,靠的是把不活跃的内存页换到磁盘上。听起来很美,实际用起来你会发现虚拟机在切换窗口的时候一顿一顿的,因为每次都要从磁盘把页面读回来。除非你就开一次做个演示,否则不要碰这个功能。
2.3 磁盘容量到底该给多少:三种典型场景的算法
磁盘这一项,我建议按"底噪 + 业务增量 + 缓冲"三段式算,而不是随便填个 20 GB 了事。
底噪指的是系统安装完之后的实际占用。14.04 桌面版完整安装大约 6 到 8 GB,选最小化安装(不装 LibreOffice、不装游戏、不装办公套件)可以压到 3 GB 左右。业务增量要看你打算干什么:只装编译器和几个开发库,2 GB 足够;要放源码仓库加编译中间产物,按源码体积的 5 到 10 倍算,因为中间.o文件和依赖缓存往往比源码本身大得多;要装数据库或者做镜像构建,那就得留 10 GB 以上。缓冲我固定留 30%,因为 ext4 文件系统本身有元数据开销,加上 apt 缓存、日志、临时文件,用久了占用会稳步上涨。
三个典型场景的推荐值:纯命令行复现环境给 15 GB,桌面开发环境给 25 GB,带数据库和容器的环境给 40 GB。
这里必须提一下虚拟磁盘的分配方式,也就是"精简置备"和"厚置备"的区别。精简置备的意思是,你声明了 25 GB 容量,但实际磁盘上只占用已经写入的那部分,比如刚装完只占 8 GB。随着你往里存东西,文件会逐渐长大,直到上限。厚置备则是一次性把 25 GB 全部占掉。前者省空间,后者性能稳。我的建议是选精简置备,因为老系统验证这类工作,空间利用率通常很低,省下来的几十 GB 能干别的。至于性能差异,在机械硬盘上有感知,在固态硬盘上基本可以忽略。
3. 新建虚拟机:每个向导页面该填什么
3.1 兼容版本与安装方式:一个必须绕开的陷阱
新建向导的第一步会让你选硬件兼容性版本。这个选项决定了虚拟机的虚拟硬件规格,选得越高,老版本虚拟机软件就越打不开。如果你不确定未来会不会把虚拟机拷给别人用,选一个中间值最保险,比如 12.x 或 14.x 这一档,兼容 2015 年之后的绝大多数版本。
真正关键的第二步是安装来源的选择。你把 ISO 镜像挂上去之后,软件通常会检测到这是 Ubuntu,然后热情地提示你"检测到支持简易安装,请输入用户名和密码"。这一步千万不要顺着走。简易安装会自动跑一个预置应答流程,跳过语言选择、跳过分区界面、跳过时区设置,直接给你装一个全盘单分区的系统。装完之后你会发现根目录只占了几十 GB 硬盘的一小块,想调整分区得重新来过。而且这套自动流程对老版本镜像的适配经常出问题,卡在某个环节不动的案例我见过不少。
正确的做法是选**"稍后安装操作系统"**,让虚拟机先建出来一个空的硬件架子,然后把 ISO 挂到光驱上,手动走完整的安装流程。多花十分钟,换来一个你能完全控制的分区结构,非常值。
3.2 硬件参数逐项设置与背后的理由
进到自定义硬件页面之后,每一项都有讲究,我按重要程度排一下。
内存和处理器前面算过了,按公式填。处理器那一栏要注意,除了"数量"还有个"每个处理器的核心数",这两个值是乘数关系。有些软件里填"处理器数量 2、每处理器核心数 2",实际总核心是 4。别只改一个就以为改完了。
网络适配器这一项决定了虚拟机怎么和外界通信,三种模式的行为差异很大:
| 网络模式 | 虚拟机能不能上网 | 宿主机能不能访问虚拟机 | 局域网其他机器能不能访问 | 适用场景 |
|---|---|---|---|---|
| 桥接 | 能,且和宿主机同级 | 能 | 能 | 需要被外部访问、需要独立 IP |
| NAT | 能,通过宿主机转发 | 能 | 不能 | 日常使用,最省事 |
| 仅主机 | 不能 | 能 | 不能 | 完全隔离的测试环境 |
我默认用 NAT。它不需要你操心 IP 规划,虚拟机起来自动拿到一个 192.168.x.x 的地址,能上网、能和宿主机互通,又不占用局域网里的 IP。如果你要做的是完全隔离的复现,选"仅主机"或者干脆把网卡移除。
I/O 控制器类型和磁盘类型这两项,我的选择是 SCSI 配 LSI Logic SAS。理由是 14.04 内核对 virtio 系列半虚拟化驱动的支持虽然存在但老版本驱动不够稳定,SCSI 模拟的兼容性最好,装完不用额外折腾驱动就能识别硬盘。千万别选 IDE,虽然它最保险,但速度慢且队列深度浅,编译大项目的时候磁盘 IO 会成为明显瓶颈。
磁盘容量按前面算的填,选"将虚拟磁盘存储为单个文件"还是"拆分成多个文件",这个选项影响不大。单个文件在复制和移动的时候更方便,多个文件在某些老文件系统(比如 FAT32)上有优势。固态硬盘上我一般选单个文件。
3.3 自定义硬件里两个容易漏掉的细节
向导走完之后,不要急着点"完成"启动,先点"自定义硬件"再检查一遍,有两项默认值需要改。
第一项是显示设置里的 3D 图形加速。这个选项默认是勾上的,对现代系统是好事,对 14.04 是灾难。14.04 自带的开源显卡驱动对虚拟 3D 的支持很有限,开了加速之后常见的症状是启动到桌面时黑屏,只有左上角一个光标在闪,或者勉强进去之后分辨率锁死在 800×600 没法调。把这个勾去掉,走纯软件渲染,虽然桌面动画会掉帧,但至少能用。
第二项是USB 控制器版本。默认可能是 USB 3.0 或 3.1,14.04 内核对 USB 3.0 的支持虽然已经存在,但遇到某些 U 盘和加密狗的时候会识别不出来。改成 USB 2.0,兼容性立刻回来。如果你的工作流里要用 USB 加密狗做授权验证,这一项一定要改。
另外顺手把声卡、打印机这些用不上的设备删掉。少一个设备就少一份中断开销,也少一个驱动加载失败的可能性。虚拟机里的声卡基本都是摆设,删了不影响任何事。
4. Ubuntu 14.04.4 安装过程逐步实录
4.1 语言选择、更新选项与那两个不该勾的框
挂上 ISO 启动,第一屏是语言选择。这里我强烈建议选English,而不是中文。原因不是崇洋媚外,而是中文环境下安装器会把/home下面的目录建成"下载""文档""图片"这样的中文名,后续在终端里做路径操作、写脚本、配置环境变量的时候,中文路径和多字节编码会给不少老工具带来麻烦,尤其是那些从 2000 年代一路传下来的构建脚本,对非 ASCII 路径的处理经常出问题。
选完语言之后是准备安装的界面,底部有两个复选框:
- Download updates while installing:不要勾。这个框会在安装过程中尝试连接官方源下载更新。14.04 的官方源早已归档,连接会超时,每个包重试几次,安装时间从十分钟变成一小时,甚至直接卡死在这一步。这是新手最容易踩的坑,我在论坛上看到的"Ubuntu 安装卡住"的帖子,十有八九是勾了这个。
- Install this third-party software:不要勾。这个选项会下载 MP3 解码器、无线网卡固件、显卡闭源驱动这些东西。虚拟机里没有无线网卡,显卡是虚拟的,这些东西下下来也用不上,只会增加失败概率。
两个框都不勾,直接点继续。安装器会警告你"不装这些可能影响体验",忽略它。
4.2 分区方案:手动分区的具体数值和操作顺序
到了安装类型这一步,选**"Something else"(其他选项)**,进入手动分区界面。全盘自动分区虽然省事,但会给你一个 20 GB 的根分区加一个 swap,后期根分区满了想扩都扩不了。
手动分区的操作顺序是这样的:先在空闲空间上建 swap 分区,再建根分区,最后如果有剩余再建/home。之所以先建 swap,是因为安装器在扫描分区表的时候对顺序敏感,先有 swap 后建根分区,识别成功率更高,这是个没什么道理但实测有效的经验。
具体数值我按 25 GB 磁盘来给:
| 挂载点 | 分区类型 | 文件系统 | 建议大小 | 说明 |
|---|---|---|---|---|
| 无(swap) | 逻辑分区 | swap area | 2 GB | 内存 4 GB 时的经验值 |
/ | 主分区 | ext4 | 12 GB | 系统、软件、临时文件 |
/home | 逻辑分区 | ext4 | 剩余全部 | 用户数据、源码、文档 |
/boot | 主分区 | ext4 | 500 MB | 可选,多系统引导时才需要 |
swap 大小这块老生常谈但还是要说:早期的经验是"物理内存的 1 到 2 倍",那是在内存普遍 512 MB 到 2 GB 的年代定的。现在虚拟机给 4 GB 内存,swap 给 2 GB 完全够用,甚至给 1 GB 也行,因为虚拟机的内存压力主要来自宿主机,而不是它自己。如果你打算做内存密集型的编译,可以按 4 GB 给。
注意:分区界面底部的"Device for boot loader installation"一定要确认是整块磁盘(比如
/dev/sda),而不是某个分区(比如/dev/sda1)。选错了会导致装完之后启动不了,屏幕上一行 "no bootable device" 或者直接进 BIOS。
建分区的时候还有一个选项容易被忽略:不要选 LVM,也不要选全盘加密。LVM 在老版本安装器上和虚拟磁盘的组合偶尔会出现卷组识别失败的问题,加密则会让你每次启动都要输密码,做快照回滚之后还可能因为密钥变化导致解不开。这两项对老系统验证场景没有任何价值,纯属给自己加难度。
4.3 用户设置与时区、键盘布局
分区确认之后,安装器会依次问时区、键盘布局、用户信息。这几步很直白,但有两个细节。
时区这一项,如果你所在的城市在列表里找不到,就选同一时区的临近城市,或者选 UTC 后面手动调整。选错时区的影响是系统时间和真实时间对不上,编译工具生成的文件时间戳会乱,某些构建系统(尤其是基于时间戳判断是否需要重新编译的 make)可能会做出错误决策。
键盘布局默认是 English (US),国内绝大多数键盘硬件都是这个布局,不用改。除非你用的是特殊布局的键盘,否则保持默认。
用户名这一项,全部用小写字母,不要带数字开头,不要带点号。这个限制不是为了好看,而是因为 Linux 系统里到处都是把用户名拼进路径和命令的地方,大小写混合或者特殊字符会在某些老脚本里触发奇怪的问题。主机名同理,小写、无下划线、长度控制在 63 字符以内。
4.4 等待安装与重启时的那句提示
确认所有设置之后,安装器开始复制文件。整个过程在固态硬盘上大约 10 到 15 分钟,界面下方会滚动显示正在安装的软件包。这个阶段不要动虚拟机窗口,也不要在宿主机上跑满 CPU 的任务,因为安装过程对磁盘 IO 很敏感,宿主机一卡,虚拟机里可能触发超时导致安装失败。
安装结束会弹出一个对话框,写着类似"Installation is complete. You must restart the computer..."的内容。这里有个经典的坑:很多人点了"Restart Now"之后,虚拟机重启,然后又回到了安装界面,以为安装失败了,反复重装。
其实原因是虚拟光驱还挂着 ISO,BIOS 启动顺序里光驱排在硬盘前面,重启后自然又从光盘引导了。解决办法有两个:一是在重启提示出来的时候,切到虚拟机软件的菜单,把光驱断开或者改成"使用物理驱动器",然后再点重启;二是不管它,等它重新进到安装界面时,直接强制关机,进虚拟机设置把光驱断开,再开机。我一般用第一种,干净。
重启之后如果看到 GRUB 菜单,然后紫色背景过渡到登录界面,就说明装成功了。第一次登录进去,桌面上会弹出几个欢迎窗口和一个软件更新提示,全部关掉,别点更新,现在更新只会卡住。
5. 首次启动后的必做配置
5.1 装增强工具:先解决编译环境这个前置条件
装完系统第一件事是装虚拟机增强工具,它决定了三件事:分辨率能不能自适应窗口、宿主机和虚拟机之间能不能复制粘贴和拖拽文件、共享文件夹能不能用。这三件事没有一件是可有可无的。
14.04 上装增强工具有两条路。第一条是装开源的open-vm-tools,源里就有,一条命令搞定:sudo apt-get install open-vm-tools open-vm-tools-desktop。第二条是挂载软件自带的 ISO 镜像,手动编译安装官方版本。前者省事,后者功能全,我的经验是先试开源版,够用就别折腾官方版。开源版对 14.04 这种老系统的支持反而更好,因为它跟着内核走,不需要每次内核升级都重编。
如果你确实需要官方版(比如要用某些高级的共享文件夹特性),那必须先准备编译环境,否则运行安装脚本会立刻报错退出:
sudo apt-get install build-essential linux-headers-$(uname -r) perlbuild-essential提供 gcc、make、libc 开发头文件,linux-headers-$(uname -r)提供当前内核版本的模块编译头文件,perl是因为安装脚本本身是 Perl 写的。这三样缺一不可,我第一次装的时候只装了 build-essential,结果脚本跑到一半提示找不到内核头文件路径,白等五分钟。
提示:
$(uname -r)这个写法会自动展开成当前运行的内核版本号,比如4.2.0-27-generic。不要手动去查内核版本再敲进去,容易敲错。
官方版安装过程中会问一堆问题,绝大多数直接回车用默认值就行,只有几个地方要注意:提示"找不到 gcc 版本"时确认路径,提示"是否启用共享文件夹"时选 yes,提示"是否启用拖拽和复制粘贴"时选 yes。全部走完之后执行sudo reboot重启,然后检查分辨率能不能随窗口缩放,能缩放就成功了。
5.2 把软件源改到归档站点:一条 sed 命令的事
前面说过 14.04 的官方源已经归档,apt-get update会一路 404。改源是必须做的一步,不改的话你连装个 vim 都装不上。
先备份一下原文件,这是我每次改系统配置文件的习惯动作:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后看一眼原文件内容,确认里面用的是哪些域名:
cat /etc/apt/sources.list | grep -v '^#' | grep -v '^$'通常你会看到archive.ubuntu.com、security.ubuntu.com、extras.ubuntu.com这几个。归档之后它们对应的位置变成了old-releases.ubuntu.com,路径前缀加上/ubuntu/。批量替换用 sed:
sudo sed -i 's|http://archive.ubuntu.com/ubuntu/|http://old-releases.ubuntu.com/ubuntu/|g' /etc/apt/sources.list sudo sed -i 's|http://security.ubuntu.com/ubuntu/|http://old-releases.ubuntu.com/ubuntu/|g' /etc/apt/sources.list sudo sed -i 's|http://extras.ubuntu.com/ubuntu/|http://old-releases.ubuntu.com/ubuntu/|g' /etc/apt/sources.list注意 sed 命令里用的是竖线|作为分隔符,不是常见的斜杠/。这是因为替换内容里本身就含斜杠,用斜杠做分隔符会出现转义地狱。这个小技巧在改路径类的配置时特别有用。
改完执行sudo apt-get update,看到一串Hit和Get而不是404 Not Found,就说明改对了。这时候可以考虑装几个基础工具:vim、git、curl、net-tools(14.04 里ifconfig还有,但装了 net-tools 更保险)、openssh-server(方便从宿主机连进去)。
5.3 时间同步:一个不痛不痒但很烦人的问题
虚拟机的时间问题是老生常谈了。宿主机看到的是本地时间,虚拟机默认按 UTC 存硬件时钟,两者差了几个小时,导致日志时间戳错乱、证书验证失败、make 反复重编译。
装完增强工具之后,时间同步是可以一键开启的:
sudo vmware-toolbox-cmd timesync enable这条命令让增强工具定期把宿主机时间同步给虚拟机。如果你装的是开源版本,命令名可能有差异,可以先which vmware-toolbox-cmd确认一下。没有这个命令的话,用ntpdate或者手动date -s也行,只是一次性的。
还有一个相关的坑:如果你做过快照回滚,虚拟机的时间会跳到快照创建的那一刻,和你当前的时间差好几天。这时候必须手动同步一次,否则从外面拉代码会报证书过期或者签名验证失败,而且报错信息往往完全不提时间问题,让人一头雾水。
5.4 快照策略:装完第一件事就打一个基线快照
配置全部完成、系统重启过一次、确认能正常用之后,立刻打一个快照,命名成baseline-clean之类能一眼看懂的名字。
这一步的价值只有在你搞砸过环境之后才能体会。我见过太多人装完系统开始折腾,装了一堆包、改了配置文件,某天把一个关键库升级坏了,想回退发现没有干净的还原点,只能从头重装。有基线快照的话,回滚两分钟搞定,回去之后重新装那个坏掉的东西就行。
快照命名我有个小习惯:前缀标明阶段,比如00-baseline、01-devtools、02-before-upgrade,按时间顺序排下来,一目了然。别用"快照1""快照2"这种名字,过两周你自己都不知道哪个是哪个。
注意:快照不是备份。快照文件是增量磁盘,挂在虚拟磁盘旁边,如果虚拟磁盘本身损坏,快照也跟着废了。重要环境该做的备份还是要做,快照只是给你提供一个快速试错的机会。
6. 踩坑实录与常见问题速查
6.1 安装阶段的高频故障与排查路径
安装阶段的问题,症状往往很吓人,但原因基本集中在几个点上。我把这些年遇到过的整理成一张表,遇到问题先照表查,比盲目搜索快得多。
| 症状 | 最可能的原因 | 处理方式 |
|---|---|---|
| 启动后黑屏,左上角光标闪烁 | 开了 3D 加速,显卡驱动不兼容 | 关机,虚拟机设置里取消 3D 加速勾选 |
| 卡在 "Downloading package files" 长时间不动 | 勾选了安装时下载更新 | 强制关机重装,两个复选框都不勾 |
| 提示 "input/output error" 后安装中止 | 光驱读取超时或 ISO 文件损坏 | 校验 ISO 的校验和,或换用物理光驱模式 |
| 分区界面看不到磁盘 | 磁盘控制器类型不兼容 | 关机改成 SCSI / LSI Logic 后重试 |
| 装完重启又回到安装界面 | 光驱仍挂着 ISO,引导顺序优先光驱 | 重启前断开光驱,或改引导顺序 |
| 提示 "no bootable device" | 引导器装到了分区而非整盘 | 重新安装,引导器选/dev/sda |
| 分辨率锁死 800×600 无法调整 | 未装增强工具 | 安装 open-vm-tools-desktop 后重启 |
补充一个表里没写的:鼠标在虚拟机里出不来。这是新手最慌的一个瞬间,以为系统卡死了。其实只要按Ctrl + Alt就能把鼠标释放回宿主机,这是虚拟机软件的默认热键。如果这个热键和别的软件冲突了,可以在偏好设置里改。
还有一个不太常见但很折磨人的:键盘输入错乱,打a出来q,打1出来别的字符。这是键盘布局选错了,通常是选成了 UK 或者其他地区的布局。解决办法是在系统设置里改回 English (US),或者临时用setxkbmap us命令切换。
6.2 使用阶段的问题:网络、复制粘贴和性能
系统跑起来之后,问题会换一批面孔。
网络连不上是最常见的。先看虚拟机右下角的网络图标有没有绿点,没有的话在虚拟机设置里确认网卡是"已连接"状态。如果网卡正常但拿不到 IP,进系统执行ifconfig(14.04 里默认有)看有没有eth0。有些情况下网卡名会变成ens33之类,这是新版命名规则,14.04 上不太会遇到。拿到 IP 之后ping一下网关,能通说明 NAT 正常,不通就检查宿主机的虚拟网卡有没有被禁用。
复制粘贴不工作,九成是增强工具没装好或者装完没重启。可以先执行ps aux | grep vmtoolsd看进程在不在,不在的话重装一遍增强工具。还有一种情况是装了开源版但没装open-vm-tools-desktop这个桌面组件包,只装了基础包,那复制粘贴功能就是不存在的。
性能不对劲,虚拟机里操作有明显卡顿但宿主机资源占用不高,先检查是不是把虚拟机文件放在了机械硬盘或者网络盘上。虚拟磁盘的随机读写性能直接决定虚拟机的响应速度,放在机械盘上编译一个中等项目能比固态盘慢三四倍。其次检查内存是不是给少了,14.04 桌面版在 2 GB 内存下会频繁换页,加到 4 GB 立刻顺畅。
6.3 三条我自己总结的避坑原则
第一条:任何配置改动之前先打快照。听起来很啰嗦,但这一条帮我省下的时间以天计。改源、装驱动、升级内核、动分区,这些操作之前都值得打一个快照。快照占的那点磁盘空间,和重装一遍系统的时间成本比,完全不值一提。
第二条:不要在虚拟机里存唯一副本。虚拟机随时可能因为快照链损坏、磁盘文件异常、宿主机重装而消失。源码、文档、配置这些有价值的东西,要么放在共享文件夹里映射到宿主机,要么定期用scp或者rsync拉出来。我现在的习惯是所有代码都在宿主机上编辑,虚拟机只做编译和运行,这样即使虚拟机炸了,重新建一个也就半小时。
第三条:记录你的每一步操作。在虚拟机桌面上放一个notes.md,每次改了什么配置、装了什么包、遇到什么问题怎么解决的,随手记两行。三个月后你回来,看这两行比你回忆半小时有用得多。老系统复现这件事,最大的成本不是操作本身,而是"当初到底改了什么"这个问题的答案丢失了。
7. 快照树、克隆与长期维护
7.1 快照树怎么设计才不混乱
快照这个东西,用得好是后悔药,用不好是绊脚石。我见过有人给一个虚拟机打了二十多个快照,快照之间还互相嵌套,最后自己都搞不清哪个是哪个分支,想删又不敢删,磁盘占用一路涨到上百 GB。
我的做法是保持一条主线加少量分支。主线就是正常的使用路径:00-baseline→01-toolchain→02-project-ready,每次完成一个阶段性配置就打一个。分支只在需要做破坏性试验的时候建,比如要试一个新版本的库会不会破坏现有环境,就在当前状态打一个exp-xxx,试完不管成不成,都回滚到主线继续。分支快照用完就删,不要留着。
快照管理界面上通常能直接看到树状结构,删快照的时候要注意,删除中间节点的快照会把它的状态合并到相邻节点,这个过程可能耗时几分钟,期间不要强制关闭虚拟机软件。
7.2 完整克隆和链接克隆的取舍
需要多台一样的环境时,用克隆比重新装快得多。克隆分两种:完整克隆是把整个虚拟磁盘复制一份,生成一个完全独立的虚拟机;链接克隆是创建一个引用父虚拟机磁盘的差分文件,新虚拟机只存变化的部分。
完整克隆的好处是完全独立,父虚拟机删了也不影响它,缺点是占空间、克隆慢。链接克隆的好处是快、省空间,缺点是必须保留父虚拟机,父虚拟机一删,链接克隆全部报废,而且性能上会有一点点损耗。
我的选择标准很明确:临时用一次的环境用链接克隆,长期保留的环境用完整克隆。比如要给同事演示一下,克隆一个链接的,演示完删掉;比如要给项目 A 和项目 B 各建一个独立环境,那老老实实做完整克隆。
克隆完成之后记得改三样东西:主机名、IP 配置(如果是静态 IP)、以及机器 ID(/etc/machine-id,14.04 上这个文件可能还不存在,用/var/lib/dbus/machine-id代替)。前两样不改会导致网络冲突,第三样不改在某些授权软件里会被认为是同一台机器。
7.3 磁盘空间的回收与虚拟机瘦身
虚拟机用久了,删掉的文件在宿主机上并不会真正释放空间,因为虚拟磁盘文件只会长大不会缩小。这个特性对精简置备的磁盘尤其明显,你可能在虚拟机里删了 10 GB 的东西,宿主机上的.vmdk文件一点没变。
回收分两步。第一步是在虚拟机内部把空闲空间清零,让文件系统知道这些块可以丢弃:
sudo dd if=/dev/zero of=/zero.fill bs=1M || true sudo rm -f /zero.fill sudo syncdd命令会往磁盘写一个全零的大文件,把剩余空间填满,然后删掉。|| true是为了防止磁盘写满时报错中断脚本,这里报错是正常的,说明空间被填满了。执行时间取决于剩余空间大小,几十 GB 的话可能要跑十几分钟。
第二步是关机,在宿主机的虚拟机设置里找到磁盘工具,执行"压缩"操作。这个操作会扫描虚拟磁盘,把全零的块标记为未使用,从而缩小文件体积。压缩过程不要中断,中断可能导致虚拟磁盘损坏。
这套流程我一般一个季度跑一次,能把虚拟磁盘从 30 GB 压缩回 12 GB 左右。如果你嫌麻烦,也可以不清理,反正现在硬盘便宜,但要知道这个空间是怎么被吃掉的,别到时候发现磁盘满了到处找不到大文件。
最后分享一个我自己长期用的小技巧:在虚拟机文件夹里放一个README.txt,写清楚这个虚拟机装的是什么系统、什么版本、预装了什么、用来干什么、最后一个快照是什么时候打的。硬盘上虚拟机多了之后,光看文件夹名你根本分不清哪个是哪个,这个文件能省下大量翻找的时间。