唠唠闲话

最近服务器硬盘故障,在修复过程中,学习了一些操作,这里做个记录。

制作 U 盘启动盘

下载镜像

Ubuntu 的版本命名遵循 “Adjective Animal” 的模式,即 “形容词+动物” 名称,每个版本都有一个官方的代号。Ubuntu 的版本还分为 LTS 和普通版,LTS 是“Long Term Support”的缩写,意味着这个版本将获得长期的支持,通常是五年。普通版本通常每六个月发布一次,支持期限为九个月。

写这篇博客的时候是 2024 年,因此建议下载至少 20.04 LTS 版本的 Ubuntu 镜像,这是一个长期支持版本,支持到 2025 年。

  1. 20.04 LTS “Focal Fossa”

    • 发布时间:2020年4月
    • “Focal”意味着“中心的”或“焦点”,“Fossa”是马达加斯加的一种猫科动物,暗示该版本稳定且聚焦于长期支持特性
    • 下载地址:https://releases.ubuntu.com/focal/
  2. 22.04 LTS “Jammy Jellyfish”

    • 发布时间:2022年4月
    • “Jammy”在英国俚语中意思是“非常幸运的”,“Jellyfish”即水母,可能是指新的长期支持版本在稳定性与新特性引入方面的“幸运平衡”
    • 下载地址:https://releases.ubuntu.com/jammy/

下载 Ubuntu 22 镜像:

1
wget -c https://releases.ubuntu.com/jammy/ubuntu-22.04.4-desktop-amd64.iso

制作启动盘

Rufus 官网下载 Rufus 工具,该工具仅支持 Windows 系统:

1
wget -c https://github.com/pbatard/rufus/releases/download/v4.4/rufus-4.4.exe

打开后,选择镜像,和 U 盘,然后开始制作启动盘。

设置持久化分区存储,这样在 U 盘上安装软件和保存文件都会被保留。如果该 U 盘仅用于系统盘,可将持久分区拉满。下图保留了部分空间用于日常存储。

20240404184538

如果不设置持久存储,启动 U 盘时将以只读模式加载操作系统,同时使用 RAM(随机访问存储器)作为临时的写入空间。这意味着使用过程中产生的数据(如临时文件、系统日志等)都存储在内存中,而不是 U 盘或硬盘上。

注:Rufus 的持久性功能被明确标记为 EXPERIMENTAL,如果希望更稳定的持久性功能,可以尝试其他工具,如 UNetbootin

启动 U 盘

开机按 F2 或 Delete 进入 BIOS 设置,找到启动项,将 U 盘启动项调整到第一位。开机后,选择语言,并选择 “试用 Ubuntu” 进入系统。

输入 ctrl + alt + t 打开终端,输入 df -h 查看硬盘信息,可以看到系统目录 / 由持久化存储分区 /cow 挂载。

软件配置

可将 U 盘当作移动的系统盘,随时随地使用。

根据需要给 U 盘安装必要软件,参考教程 Ubuntu 教程(一) | 必备软件的安装和配置

如果在校园网下无法联网,通过局域网 IP 安装联网脚本:

1
2
# 如果是 zsh 用户,使用 | zsh
curl http://172.23.148.40:9080/cubenlp/ecnu_login_install.sh | bash

20240406223411

默认的 APT 源不完整,搜索不到 testdisk 等应用,需要修改。以下为 22 版本的 apt 源:

1
2
3
4
5
6
7
8
9
10
11
12
13
# cd /etc/apt
# cp sources.list sources.list.bak
# nano sources.list
deb http://archive.ubuntu.com/ubuntu jammy main restricted
deb http://archive.ubuntu.com/ubuntu jammy-updates main restricted
deb http://archive.ubuntu.com/ubuntu jammy universe
deb http://archive.ubuntu.com/ubuntu jammy-updates universe
deb http://archive.ubuntu.com/ubuntu jammy multiverse
deb http://archive.ubuntu.com/ubuntu jammy-updates multiverse
deb http://archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu jammy-security main restricted
deb http://archive.ubuntu.com/ubuntu jammy-security universe
deb http://archive.ubuntu.com/ubuntu jammy-security multiverse

更改 apt 源后,开始安装软件:

1
2
3
4
5
sudo apt update
sudo apt install net-tools vim testdisk curl git network-manager gddrescue lvm2 -y
# 可选,用于 ssh 连接和网络挂载
sudo apt install openssh-server sshfs -y
sudo apt install python3 python3-pip -y

实测用 Rufus 安装的 U 盘启动盘,在启动时,有可能会重置主机名和默认登录用户。因此建议创建新用户,并在新用户上配置环境。

网络设置

Netplan 会读取 /etc/netplan/ 目录下的所有以 .yaml 结尾的文件来构建整个系统的网络配置。如果目录中有多个配置文件,Netplan 会按字母顺序合并这些文件。

查看默认 netplan 配置文件:

1
2
3
4
# cat /etc/netplan/01-network-manager-all.yaml
network:
version: 2
renderer: NetworkManager

网络配置由 NetworkManager 服务管理,NetworkManager 是一个动态网络管理工具,它可以自动检测和配置网络连接,使得用户在大多数情况下无需手动配置网络。

部分情况需手动修改,可通过以下方法之一来查看系统中所有网络接口的名称:

  • 执行 ip linkip a 命令在终端中查看。
  • 使用 ifconfig 命令(如果已安装 net-tools 包)。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
network:
ethernets:
enp195s0: # 接口名称,通过 ip link 查看
addresses: [192.168.98.26/24]
eno2:
addresses: # 静态 IP 地址
- 172.23.148.35/24
# 网络配置
gateway4: 172.23.148.1
nameservers:
addresses:
- 114.114.114.114
search: []
version: 2

接口名称的含义:

  • en 表示以太网(Ethernet)。
  • o 表示 onboard(板载设备)。
  • s 表示 hotplug slot(热插槽)。
  • x 表示 MAC地址(通常用于无法通过其他方式分类的情况)。
  • 数字表示物理位置或者是内部编号,如 eno1 通常指的是第一个板载以太网接口。

修改配置后,执行 sudo netplan apply 使配置生效。

修改日志规则

默认情况下,Ubuntu 系统日志使用 rsyslog 服务来记录系统事件,按时间轮转。

1
2
cd /etc/logrotate.d
cat rsyslog

内容形如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/var/log/syslog
/var/log/kern.log
...
/var/log/debug
/var/log/messages
{
rotate 4
weekly
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}

前边是指定的日志文件,大括号 {} 内的是对这些文件应用的具体规则:

  • rotate 4:保留最新的4个轮替文件。超过这个数量的旧文件会被删除。
  • weekly:日志文件将每周轮替一次。
  • missingok:如果日志文件不存在,不会报错。
  • notifempty:如果日志文件为空,不进行轮替。
  • compress:轮替的日志文件将被压缩(默认使用gzip)。
  • delaycompress:压缩操作将延迟到下一次轮替周期。
  • sharedscripts:这个选项意味着 postrotate 脚本将只执行一次,而不是对每个日志文件执行一次。
  • postrotate/endscript:这是一对指令,定义了在日志文件轮替后需要执行的脚本。

比如将 weekly 改为 size 100M 选项,指定日志文件达到一定大小时进行轮替,避免异常占用。

执行 sudo logrotate -f /etc/logrotate.conf 使配置生效。

异常处理

U 盘运行 ddrescue 时,没限制日志大小,把电脑卡死了,导致重启一直卡在光标处进不了系统。

在论坛翻到了一个进入命令行系统的方案:Ubuntu boots to a black screen with blinking a underscore character after release upgrade

开机选择安全模式,卡在光标处的时候,按 Ctrl + Alt + F1Ctrl + Alt + F3 切换到命令行模式。

最后通过命令行发现了该问题: U 盘的 /var/log/syslog/var/log/kern.log 把持久化内存撑爆了,导致系统无法正常启动。

清理并刷新系统日志:

1
2
3
4
cd /var/log
sudo echo > syslog
sudo echo > kern.log
sudo systemctl restart rsyslog

重新输入 df -h 查看硬盘占用信息。

备份系统

默认的两个分区,一个是只读的 squashfs,另一个是持久化的 ext4。

这种特别设计用于支持 Ubuntu Live 环境中的数据持久性。在这种环境中,系统文件是以特定的方式存储和管理的,以允许从 read-only 的 Live 系统(如 ISO 映像)启动,同时能保存用户的修改和系统的更新到一个持久的存储空间。

BIOS 模式下只识别到 U 盘的存储盘分区,没识别到 UEFI 分区,可能因为引导分区存在损坏。借这个机会,学习 Grub 的安装,以及挂载系统的基础原理。

U 盘备份

交换机网络重启

服务器之间加装了交换机,共享文件存储。有时会遇到某个设备与其他设备无法通信,此时可以尝试重启该设备的网络:

1
2
3
ip addr # 确认网络接口
sudo ip link set ens8 down
sudo ip link set ens8 up

硬盘维护

硬盘维护策略和分区备份方案。

查看硬盘信息

获取硬盘挂载信息的几个命令:

常见命令 用处
lsblk 列出所有可用的存储设备及其分区,包括设备的挂载点、大小等信息
fdisk -l 显示磁盘分区表信息,包括分区大小、类型等(需 sudo 权限)
blkid 列出所有设备的 UUID 等信息,也可以用于识别设备类型
pvdisplay 显示物理卷信息
vgdisplay 显示卷组信息
lvdisplay 显示逻辑卷信息
lshw 列出系统的硬件配置的命令,-short 选项以简短格式输出硬件详情
lsblk -d -o name,rota 查看硬盘类型,0 代表 SSD,1 代表 HDD,也即旋转设备

举个例子,通过 fdisk -l 来判断设备信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
root@rex-pc:/home/rex# fdisk -l
...

Disk /dev/sda:111.81 GiB,120034123776 字节,234441648 个扇区
Disk model: Tigo SSD
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:gpt
磁盘标识符:A941E272-3C6A-4047-AE14-02D922808DDD

设备 起点 末尾 扇区 大小 类型
/dev/sda1 2048 1023999 1021952 499M Windows 恢复环境
/dev/sda2 1024000 1228799 204800 100M EFI 系统
/dev/sda3 1228800 1261567 32768 16M Microsoft 保留
/dev/sda4 1261568 234440703 233179136 111.2G Microsoft 基本数据

Disk /dev/sdb:119.25 GiB,128035676160 字节,250069680 个扇区
Disk model: SanDisk SDSSDHP1
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x3ace8513

设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/sdb1 * 2048 1050623 1048576 512M b W95 FAT32
/dev/sdb2 1052670 250068991 249016322 118.8G 5 扩展
/dev/sdb5 1052672 250068991 249016320 118.8G 83 Linux
...

比如这里装了两个系统:/dev/sda 是一个 120GB 的 Tigo SSD 硬盘,有 4 个分区,挂载 Windows 系统;/dev/sdb 是一个 120GB 的 SanDisk 硬盘,有 2 个分区,挂载 Linux 系统。

刷新硬盘信息

如果硬盘发生了变化但系统未识别到,比如做了分区,修复,dd 拷贝,可以用 partprobe 命令刷新分区表,使系统重新识别硬盘:

1
sudo partprobe

此外,如果逻辑卷未被识别,可以用 vgchange 命令激活:

1
sudo vgchange -ay

错误检查及修复

e2fsck 是专门用于检查和修复 ext2、ext3、或 ext4 文件系统的工具,可以检测文件系统中的不一致性和潜在错误,并尝试修复这些问题。这个工具通常在文件系统损坏或不正常关机后运行。fsck 是一个更通用的文件系统检查和修复命令,用于多种类型的文件系统(比如 xfs、btrfs等),fsck 会根据文件系统类型自动选择合适的工具来执行检查和修复操作。针对ext2/ext3/ext4文件系统,fsck 会调用 e2fsck

基本的命令格式如下:

1
e2fsck [选项] 设备
  • [选项]:例如,-p 以只读模式运行,-y 在发现问题时自动尝试修复,-f 强制检查文件系统
  • 设备:这是要检查的文件系统的设备名,例如 /dev/sda1

示例:使用 e2fsck 命令检查和修复文件系统错误,比如:

1
2
3
4
5
6
7
8
9
10
11
12
root@rex-pc:~# e2fsck -b 32768 /dev/sdd2
e2fsck 1.45.5 (07-Jan-2020)
casper-rw 未被彻底卸载,强制进行检查。
第 1 遍:检查 inode、块,和大小
第 2 遍:检查目录结构
第 3 遍:检查目录连接性
第 4 遍:检查引用计数
第 5 遍:检查组概要信息
#0 的可用块计数错误(16232,counted=0)。
处理<y>? 是
#1 的可用块计数错误(32635,counted=0)。
处理<y>? 是

当硬盘容量非常大时,e2fsck 可能需要相当长的时间来完成检查,且检查过程无法中断。

badblocks 用于扫描磁盘中损坏区域(坏块)的工具,识别硬盘或存储设备上的物理损坏部分。基本命令格式如下:

1
badblocks [选项] 设备

常用选项:

  • -v:显示详细过程。这个选项会让badblocks在执行时显示更多的信息,有助于了解检查进度和结果。
  • -s:显示进度条。这个选项会在检查过程中显示一个进度条,让用户可以直观地看到检查进度。
  • -w:使用写入测试。这是一种破坏性测试,会写入数据到每个扇区然后读取,以此来检测坏块。注意,这会覆盖磁盘上的数据,请在数据备份后使用。
  • -n:非破坏性测试,进行读写测试但不会覆盖数据,适用于包含有价值数据的磁盘。
  • -o 文件名:将找到的坏块列表输出到指定的文件中。

示例(似乎要等待较长时间):

1
2
3
root@rex-pc:~# badblocks -v /dev/sdd
正在检查块 0 到 61439999
检查坏块(只读测试):

硬盘备份

如果硬盘使用时间长,经常出现坏扇区的情况,可以用 dd 命令,将其复制到另一个硬盘。

特别注意,ifof 端不能弄反,否则可能直接导致硬盘被覆盖或信息不完整

拷贝磁盘示例:通过 lsblkdf -h 确认需要拷贝的硬盘,比如将 /dev/nvme1n1 复制到 /dev/sdm

1
sudo dd if=/dev/nvme1n1 of=/dev/sdm bs=4M status=progress

常用参数说明:

  • if=<file>:指定输入文件(Input File),也可以是设备。
  • of=<file>:指定输出文件(Output File),同样也可以是设备。
  • bs=<bytes>:设置每个块的大小,例如 bs=4M 意味着每个块是4MB。
  • count=<number>:拷贝块的数量,用于确定总共需要拷贝多少数据。
  • skip=<number>:跳过输入文件开头的块数。
  • seek=<number>:跳过输出文件开始的块数。
  • conv=<conversion>:指定转

如果硬盘较大,bs 值应该调高,比如 4M,默认值为 512Byte

拷贝需等待较长时间,完成后,输出形如:

1
2
15261915+ records in
15261915+ records out

此时执行 lsblk 不会看到变化,但 fdisk -l 能看到新拷贝硬盘的分区信息。也可以通过 partprobe 命令刷新分区表:

1
partprobe /dev/sdm

完成后,可以进行挂载,测试文件信息。

除了拷贝到硬盘,也可以拷贝为镜像,比如:

1
dd if=/dev/sda1 of=/path/to/backup.img bs=4M

然后进行恢复:

1
dd if=/path/to/backup.img of=/dev/sda1 bs=4M

故障硬盘备份

官方手册:https://www.gnu.org/software/ddrescue/manual/ddrescue_manual.html

访问加速:https://superuser.com/questions/413650/is-there-any-way-to-speed-up-ddrescue

GNU ddrescue 是一个数据恢复工具,用于从一个文件或块设备复制数据到另一个文件或块设备,特别是在源设备出现读取错误时。它尝试首先恢复好的部分,以防读取错误导致的数据损坏。ddrescue 在进行数据恢复时非常有用,特别是在处理有物理损伤或者坏道的硬盘时。

基本用法

1
ddrescue [options] infile outfile [mapfile]

其中 infile 是源文件/设备,outfile 是目标文件/设备,而 [mapfile] 是用来记录进度和恢复信息的映射文件,允许中断和恢复恢复过程。

主要参数:

  • -a, --min-read-rate=<bytes>:指定好的区域的最小读取速率,低于此速率的被认为是坏区。
  • -b, --sector-size=<bytes>:指定输入设备的扇区大小,默认为512字节。
  • -d, --idirect-D, --odirect:分别使用直接磁盘访问模式读取输入文件和写入输出文件,可以绕过缓存。
  • -f, --force:强制覆盖输出设备或分区。
  • -n, --no-scrape-N, --no-trim:跳过刮擦阶段或修剪阶段,这些阶段用于尝试从坏区恢复数据。
  • -r, --retry-passes=<n>:设置重试次数,-1 表示无限重试。
  • -s, --size=<bytes>:指定要复制的输入数据的最大大小。

以下是一个基本的 ddrescue 命令示例,它会创建一个映射文件来记录进度,以便在需要时可以恢复复制过程:

1
ddrescue -f /dev/sdf /dev/sde rescue_mapfile.log

注意指定日志文件,避免异常中断后重新开始。

ddrescue 会先“拯救”好的区域,也即修复 non-tried 区域,完成后开始修复坏区。坏区有两个阶段,速度均非常慢。个人尝试在 splitting 阶段终止修复,实测重启后,能正常挂载硬盘和读取数据。

1
2
Trimming failed blocks...
Splitting failed blocks...

拷贝数据

硬盘修复完成,重新挂载代替原来的系统盘即可。如果修复后不作为系统盘,可通过 rsync 来拷贝,比如:

1
rsync -avzP /mnt/home /home

此外,使用 ls -ln 能查看 /home 子文件夹的 UID 和 GID。

借此恢复用户组信息,通过 groupadduseradd 命令和指定参数,确保 UID 和 GID 与原始系统一致:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
users_info=(
"user1:1004:1004"
"user2:1013:1013"
)

for info in "${users_info[@]}"
do
IFS=':' read -r username uid gid <<< "$info"
# 如果不存在,先创建组
if ! getent group "$user" &>/dev/null; then
groupadd -g "$gid" "$username"
echo "组 $username 已创建,GID: $gid"
fi
# 然后再创建用户
if ! id "$username" &>/dev/null; then
# 添加用户,指定UID和GID,并创建家目录(-m)
useradd -g "$username" -u "$uid" -m "$username"
echo "用户 $username 已创建,UID: $uid, GID: $gid"
# 清除密码
# passwd -d "$username"
fi
done

逻辑卷

逻辑卷管理是 Linux 系统中的一种高级磁盘管理技术,它允许用户将多个硬盘分区组合成一个逻辑卷,以提供更大的存储空间。逻辑卷管理的好处是可以动态调整逻辑卷的大小,而无需重新分区或格式化硬盘。

其他

查看硬盘使用时间

TODO。

1
2
sudo apt install smartmontools
sudo smartctl -a /dev/sda

nvme 工具:

1
2
sudo apt install nvme-cli
sudo nvme smart-log /dev/nvme0

分区和挂载

挂载与卸载:

1
2
3
4
5
6
7
8
9
10
# 挂载硬盘
mount /dev/sdb1 /mnt
# 卸载硬盘
umount /mnt
# 查看挂载信息
df -h
# 查看硬盘占用进程
fuser -m /mnt
# 关闭硬盘挂载,需要先关闭占用进程
fusermount -u /mnt
  • fuser 检查特定文件、文件系统、或网络端口的占用情况,并返回正在使用它们的进程的 PID(进程标识号)
  • fusermountFUSE(Filesystem in Userspace)的用户空间程序,允许普通用户不用通过系统管理员权限就挂载文件系统。FUSE 是 Linux 内核的一个模块,允许创建完全在用户空间的文件系统,提高了安全性和灵活性。例如,通过 FUSE,用户可以挂载远程目录、虚拟文件系统等。

通常可以用 chroot 命令进入挂载设备,模拟对该设备的登录,比如:

1
2
3
mount /dev/sda1 /mnt # 挂载系统盘
cd /mnt
chroot /mnt

修改分区信息,使开机自动生效。(待补充)

1
vim /etc/fstab