Posted in: Ubuntu/Linux

把物理服务器的 CentOS 7 升级到 Ubuntu 24,惊心动魄

工作单位有一台服务器购买于 2020 年,安装的是 2020 年发布的 CentOS 7.8 系统。但其实 CentOS 7.0 是在 2014 年发布的,7.X 的大部分 package 版本都很老,实际上使用起来非常困难。众所周知 CentOS 7 在这个星期(2024年6月30日之前)就结束支持了,整个 CentOS 项目也寿终正寝。上级管理员让我们想对策,我就决定换成 Ubuntu 24.04 LTS,毕竟 LTS 之间升级起来比较方便。

我自认为有多次安装 OS 的经历,以为这件事情很简单,只需要 1 个小时就能搞定现场工作(开启 SSH 之后就可以离开现场、去工位上配置剩余内容)。万万没想到各种坑源源不断,现场操作了 5 个多小时,差点吃不上午饭。全部配置完成则用了一整天。

一、U盘无法识别

原以为 2024 年了现在的 Linux 发行版可以在本地硬盘上安装,结果查了一下还是不行,必须要找一个 U 盘。于是在家里翻墙倒柜找出了一个从🇨🇳带来的金斯顿 U 盘,连帽子都没有了。虽然很破,但它的插口是蓝色的,也就是说支持 USB 3.0。这点还不错。

1-1、下载 Ubuntu 镜像 iso

Desktop 的 iso 文件是 6 GB,而 Server 的 文件是 2.7GB,为了下载方便就选择了 Server(事实证明我选对了,因为服务器的 USB 接口隐藏在深处,连接鼠标不方便操作)。

1-2、刻录到 U 盘

这里遇到大坑了。因为我手头上只有 mac 电脑,可用的软件有限。我尝试了两种方法:

  1. balenaEtcher。这是 Ubuntu 官网介绍的方法
  2. 用 dd 命令。这是 ChatGPT 介绍的方法。

不论用哪种方法,刻录完之后、U 盘在自己的 mac 上无法识别,插到服务器上也无法识别。原因不明。

后来改用 unetbootin 解决。可是 unetbootin 只有 Intel 编译版本,没有 apple silicon 编译版本。我之前为了省电和预防病毒,已经把 Rosetta2 删除了。只好先把它安装回来,操作完之后才删掉。

就这样,光到这一步,已经折腾了一个上午。食堂的自助餐早就被抢完了。

删除 Rosetta2 的方法

1-3、重启机器,从 BIOS 选择用 U 盘启动

再次遇到坑。首先因为机器是小牌子,不知道按键盘哪个键进入 BIOS。网上搜不到,也没想问别人(在🇯🇵一般尽量不麻烦别人)。那就自己尝试吧。尝试了 F2、F12等,都不行。

后来按下 Ctrl+A,进入了 RAID 专用的 BIOS。这里虽然也能选择“boot 设备”,但一个也选不了。显然这个“boot 设备”是跟 RAID 相关,跟安装操作系统无关。

后来看到屏幕上有 “Press ESC or DEL to enter setup”,我就试了按下 DEL。进去了。原来硬件商一般把 BIOS 叫做 “setup”。有意思。

这个 BIOS 界面类似于右图,和我以前见过的很像。从这里很容易设置 Boot。坑又来了:我的优盘是金斯顿(Kingston),可是 Boot 选项里面出现了两个 Kingston,后面跟着一大串我看不懂的词语。该选哪个?😂😂😂

很明显这是在刻录 U 盘时出现了两个分区,只有一个是正确的。死马当活马医,碰碰运气吧。

我先选择第一个,保持设置、重启。过了好久机器黑屏、叫天天不应叫地地不灵。😫

选错了,怎么退出重来?我想了一下,把 U 盘拔下来,很快机器就进入之前的 OS 了。

再重启进入 BIOS,选择第二个 Kingston。保持设置、重启。终于出现了像右图那样的 Ubuntu 安装界面!

二、网络设置中的 Subnet

这台服务器是手动设置的固定公网 IP(假设是123.45.123.155),之前从 CentOS 7 那里备份的网络信息如下(信息已脱敏处理):

IPADDR=123.45.123.229
NETMASK=255.255.255.192
BOOTPROTO="static"
DEVICE=enp96s0f0
ONBOOT=yes
IPV6INIT=no
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
PREFIX=26
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
NAME="System enp96s0f0"
GATEWAY=123.45.123.191
DNS1=8.8.8.8
DNS2=1.1.1.1

安装过程中有一步是要设置网络。第一个空格就傻眼了:什么叫做 Subnet?

开始,我把 NETMASK (255.255.255.192)填入,显示格式不对,需要 XXX.XXX.XXX.XXX/YY 的格式。

于是我加上 /26,显示还是不对,说“目标 IP 不在这个方位内”(当然是英文的提示)。

安装个系统还要变成网络专家吗?最后在网上寻找了一个计算器才解决。原来这个 Subnet 又叫做 CIDR。比如这个例子里面,Subnet 是 123.45.123.192/26。真是醉了。

三、硬盘分区与选择 boot 设备

因为这是一台工作服务器,上面已经有一大堆数据了。虽然已经备份,但总是希望原来的能保留下来。架构是这样的(信息已脱敏处理):

/dev/sda1: 1MB, bios_grub
/dev/sda2: 500MB,/boot
/dev/sda3: 500GB, /
/dev/sda4: 8GB, swap
/dev/sda5: 50TB, /home
/dev/sdb1: 1TB, /other/place1
/dev/sdc1: 1TB, /other/place2

其中 /dev/sda5(/home) 用了不少空间,/dev/sdb1(/other/place1) 用了一小部分,/dev/sdc1 (/other/place2)基本上没用过。

设置硬盘分区的界面如右图所示。以前我在 PC 上 安装桌面版 Ubuntu 时、以及在服务器上安装 CentOS 时,类似的内容已经设置过很多次了:不需要格式化的(例如 /home)选择“维持原来的格式”即可。因此自认为这一步应该非常容易。没想到坑又来了。

原来、屏幕顶端一直提示:“请选择一个设备用于 boot ”。那就选呗。毫无疑问 /dev/sda 是我的主硬盘,按常理推断肯定选 /dev/sda 作为 Boot Device。结果傻眼了:/dev/sda 的“Use As Boot Device”选项不可用!更有意思的是,/dev/sdb 和 /dev/sdc 的“Use As Boot Device”选项也不可用!这下子麻烦了,无法前进了。

网上搜了一番才发现,原来需要硬盘上不能有已存在的分区。那就选 /dev/sdc 了,上面没数据,可以直接格式化。操作完之后发现系统在 /dev/sdc 上面自动创建了一个分区挂载到了 /boot/efi,大小约为 1G,格式是 FAT32。

真是不幸中的万幸。如果我的 /dev/sda、/dev/sdb、/dev/sdc 都已经有数据了,那麻烦就大了,因为无法新建 /boot/efi 分区,这安装就无法前进了。然后就这么一步一步前进,终于设置完成、开始安装了:

四、安装完成

安装完之后系统会提示你重启。这时首先把 U 盘拔下来,然后重启进入 BIOS, 选择硬盘作为 Boot 设备。保存设置、重启,然后结果就是:

惊不惊喜、意不意外?🤡

这个界面非常难操作,我甚至发现键盘上按下的是“)”,屏幕上显示的却是“(”。而且也搜不到重启系统的方法。无奈强行按下服务器的电源键重启。

再次进入 BIOS,猜想是 Boot 设备选择错误。于是在列表里寻找,想到之前在操作“Use As Boot Device”时,系统不是创建了一个分区挂载到了 /boot/efi 上吗?而列表里面正好有一个叫做 USB EFI KEY 的条目(回忆的,没有拍下照片。当时紧张得不行😓)。选了它,保存设置、重启,居然进入了安装好的 Ubuntu。

原来 /boot/efi 是一个虚拟的 USB 设备?

五、与 Apache 相关的各种难题

这台服务器主要用于运行网站数据库服务,网站的程序是 Apache。在 CentOS 时代叫做 httpd,但在 Ubuntu 里面叫做 apache2 。名字是 httpd 好听一点,apache2 那个 2 怪怪的,如果哪天出了 v3.X 版怎么办?不过既然已经选择 Ubuntu 了,只能把习惯改一改。

5-1、设置 server-info:被 ChatGPT 坑了

ChatGPT 告诉我只要这样子配置就好了:

<Location /server-info>
    SetHandler server-info
    Require local
    Require ip 192.168.0   # Replace with your network or IP range for remote access
</Location>

结果配置完之后死活不行,一直显示 404。后来才发现,原来 Ubuntu 的 Apache 已经内置了很多“模块开关”,但是没有启用。server-info 就是其中一个,启用方法是:

a2enmod info

本质上是把 /etc/apache2/mods-available 目录下面的 info.confinfo.load 链接到了 /etc/apache2/mods-enabled。而 ChatGPT 给的答案只做了 conf 没有做 load,自然不行了。当然 a2enmod 可以解决模块之间的依赖问题,这是与直接手动做链接的区别。

5-2、PhpMyAdmin:必须要密码

安装 MySQL 之后,root 可以直接登录不需要密码。我就想能否让 root 免密码去登录 PhpMyAdmin,结果是不行。必须新建一个用户,权限可以和 root 一样。但要有密码。真是多此一举啊。

5-3、利用 Python 重新编译 WSGI 模块

如上所述,我的项目是 Flask 实现的,Flask 是通过 WSGI 模块整合进入 Apache 服务器的。

在老的 CentOS 7 系统中,自带的 Python 和 WSGI 版本都很老,不能用。所以我的项目用 Conda 构建,WSGI 也是用 Conda 下面的 Python 编译出来,然后手动加载到 Apache 里面的。

现在装了最新的 Ubuntu 24,自带的 Python 和 WSGI 版本都很新,比我的项目中的 Python 还新。由于我的项目非常庞大,版本已经全部锁死,不能随便切换。所以最开始的设想是:把原来编译的 WSGI 模块直接加载进入 Apache。结果一测试(访问网页),直接卡死。一查看 log,一大堆报错显示找不到 httpd。搞笑,Ubuntu 里面哪有 httpd,明明是叫 apache2 的。可见老的那个编译的 WSGI 模块已经不能用了。

那么就需要重新编译:

# 进入 conda 环境
pip3 install mod_wsgi==X.X.X

我就知道不会一帆风顺。果不其然又出错了:

# ... 一大堆 log
~/miniconda3/envs/myenv/compiler_compat/ld: /lib/x86_64-linux-gnu/libc.so.6: unknown type [0x13] section .relr.dyn'

直接把这个 log 扔给 ChatGPT,显示:输入文本过长,无法回答……

只好自己找解决方案了,不知经过多少波折,总算发现了。原因是:~/miniconda3/envs/myenv/compiler_compat/ld 的版本太低了,无法对 /lib/x86_64-linux-gnu/libc.so.6 (这是 Ubuntu 24.04 系统的文件) 进行操作。解决方案是:用 /usr/bin/ld (来自 Ubuntu 24.04 系统)复制替换掉 ~/miniconda3/envs/myenv/compiler_compat/ld 。总之挺无语的。

六、没有 tmpwatch

我的项目是数据库网站,用户访问之后会留下很多临时文件。tmpwatch 是处理临时文件的好工具,没想到 Ubuntu 居然没有 tmpwatch!但有个李鬼:tmpreaper 。用法接近。

Comments (8) on "把物理服务器的 CentOS 7 升级到 Ubuntu 24,惊心动魄"

  1. Firefox 121.0 Android 6.0.1

    我每隔一段時間就要裝一個Ubuntu新系統,但是24.04達到了6G,而我十多年前買的金士頓U盤只有4G,再無法把它做成最新版的Ubuntu安裝盤了。

  2. Firefox 118.0 Windows 10 x64 Edition

    用Ubuntu不如直接用Debian,Canonical可比RedHat噁心多了

    另外好奇問一句這個獨服是什麼配置,是經典Xeon E5/E3老古董嗎 😆 ,看日本本土商家的VPS貴/配置差/帶寬小/流量少,還不如用AWS划算……本博客應該不是放日本服務器的吧

    1. Safari 17.5 Mac OS X  10.15.7

      这个 blog 是在甲骨文免费的 vps 上,位置在日本,但用了 Cloudflare CDN。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注