适用:RHEL / CentOS / Anolis / Rocky / AlmaLinux 8 系、Ubuntu / Debian、Fedora。
重点覆盖“联网机下载 → 离线服务器安装”的场景。
文中 Anolis 8.6 + 内核 4.18 的组合已在 15577 实测通过。
0. 一句话原理
Linux 要挂载 exFAT,需要两样东西:
- 一个 exFAT 驱动:内核 ≥ 5.4 用原生
exfat模块;内核 < 5.4(如 RHEL/Anolis 8 的 4.18/4.19)用用户态 FUSE 驱动fuse-exfat。 - 能识别文件系统的工具:
blkid读取卷引导记录(VBR)偏移 3 处的EXFAT标识,认出TYPE="exfat"。
modprobe exfat 报 module exfat not found 只说明当前内核没编这个模块,不代表不能挂 exFAT——装 FUSE 版即可。
1. 识别链路:四层排查
| 层 | 负责者 | 检查命令 | 正常表现 | 失败表现 |
|---|---|---|---|---|
| 1. USB 枚举 | usb-storage / uas + udev |
dmesg -w、lsusb |
[sdb] Attached SCSI removable disk |
没有 /dev/sdX |
| 2. 分区扫描 | 内核分区解析 | lsblk -f、fdisk -l |
有 /dev/sdb1 |
只有 /dev/sdb |
| 3. 文件系统识别 | blkid / libblkid |
blkid /dev/sdb1 |
TYPE="exfat" |
TYPE 为空或 vfat |
| 4. 挂载 | 内核 exfat 或 FUSE mount.exfat |
mount -t exfat |
挂载成功 | unknown filesystem type |
exFAT 的 VBR 特征:偏移 0x003 起 8 字节为 EXFAT ,偏移 0x1FE 为 55 aa。
# 一次性看全
lsblk -o NAME,SIZE,TYPE,FSTYPE,LABEL,MOUNTPOINTS
sudo blkid /dev/sdb1
sudo file -s /dev/sdb1
# 原始字节确认(blkid 认不出时)
sudo hexdump -C -n 512 /dev/sdb1 | head -4
2. 先判断内核支持哪种方案
uname -r
grep -i exfat /proc/filesystems
# 有 /proc/config.gz 时:
zgrep CONFIG_EXFAT /proc/config.gz 2>/dev/null
# 否则:
grep CONFIG_EXFAT /boot/config-$(uname -r)
modinfo exfat 2>&1
判读:
| 输出 | 结论 | 做法 |
|---|---|---|
/proc/filesystems 有 exfat |
内核已支持(内置或已加载) | 直接 mount -t exfat |
CONFIG_EXFAT_FS=y |
驱动编译进内核 | 直接挂载,忽略 modprobe 报错 |
CONFIG_EXFAT_FS=m 且 modinfo 有 |
模块存在 | sudo modprobe exfat 后挂载 |
没有该配置 / modprobe not found |
内核不支持 | 装 FUSE 方案(见第 3 节) |
常见发行版对照:
| 发行版 | 内核 | exFAT 支持 |
|---|---|---|
| RHEL / CentOS / Anolis / Rocky / Alma 8 | 4.18 / 4.19 | ❌ 无,需 fuse-exfat |
| RHEL 9 / Rocky 9 / Alma 9 | 5.14 | ✅ 原生 |
| Ubuntu 20.04 | 5.4(staging) | ⚠️ 部分在 linux-modules-extra,找不到就用 FUSE |
| Ubuntu 22.04+ / Debian 11+ | 5.15 / 5.10+ | ✅ 原生 |
| Fedora 33+ | 5.7+ | ✅ 原生 |
内核 5.4 首次合入 exFAT(staging),5.7 转入fs/exfat转正。部分发行版把模块拆进linux-modules-extra-$(uname -r)。
3. 在线机器上安装(让本机先能挂)
3.1 内核 ≥ 5.4(Ubuntu 22.04+、Debian 11+、RHEL 9、Fedora)
挂载本身不需要装包;建议装 exfatprogs 以便格式化和修复:
# Debian / Ubuntu
sudo apt update
sudo apt install exfatprogs
# RHEL 9 / Fedora / Rocky 9
sudo dnf install exfatprogs
挂载:
sudo mkdir -p /mnt/usb
sudo mount -t exfat -o uid=$(id -u),gid=$(id -g),umask=022 /dev/sdb1 /mnt/usb
3.2 内核 < 5.4:RHEL / CentOS / Anolis 8(FUSE 方案)
关键事实:EPEL 8 没有 fuse-exfat,它在 RPM Fusion free EL8;exfat-utils 已过时,用 exfatprogs 替代。
# 1) EPEL(提供 exfatprogs,也是 RPM Fusion 的前置)
sudo dnf install -y epel-release
# 2) RPM Fusion free EL8(提供 fuse-exfat)
sudo dnf install -y \
https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm
# 3) 安装
sudo dnf install -y fuse-exfat exfatprogs
# 4) 验证
rpm -q fuse-exfat exfatprogs
command -v mount.exfat mkfs.exfat fsck.exfat
3.3 内核 < 5.4:Ubuntu / Debian 老版本
sudo apt update
sudo apt install -y exfat-fuse exfatprogs
# 老发行版若没有 exfatprogs,用 exfat-utils 提供 exfatfsck/mkfs.exfat
# sudo apt install exfat-fuse exfat-utils
3.4 挂载与权限
lsblk -o NAME,SIZE,TYPE,FSTYPE,LABEL
sudo mkdir -p /mnt/usb
# 优先走 mount 的类型分发(内核原生或 /sbin/mount.exfat helper)
sudo mount -t exfat -o uid=$(id -u),gid=$(id -g),umask=022 /dev/sdb1 /mnt/usb
# 若报 unknown filesystem type,直接调用 FUSE 挂载器
sudo mount.exfat -o uid=$(id -u),gid=$(id -g),umask=022 /dev/sdb1 /mnt/usb
findmnt /mnt/usb
说明:
- FUSE 挂载在
mount/findmnt里显示为type fuseblk,这是正常的,不代表没挂上 exFAT。 - 普通用户访问靠
uid=、gid=、umask=控制;FUSE 还支持allow_other(需/etc/fuse.conf开user_allow_other)。 - 桌面环境可用 udisks2 自动挂载:
udisksctl mount -b /dev/sdb1,挂载点通常在/media/$USER/LABEL。 - U 盘无分区表(整盘格式化)时,直接挂
/dev/sdb而不是/dev/sdb1。
卸载:
sync
sudo umount /mnt/usb
# 或
udisksctl unmount -b /dev/sdb1
4. 联网机器下载离线包
4.1 先确认目标离线机的三件事
在离线机上执行(或让用户提供):
cat /etc/os-release # 发行版 + 大版本
uname -m # 架构:x86_64 / aarch64
uname -r # 内核:决定用原生还是 FUSE
rpm -q fuse fuse-libs fuse-common 2>/dev/null || true
原则:
- RPM/DEB 必须匹配发行版大版本和 CPU 架构;x86_64 的包不能装到 aarch64。
- 内核 < 5.4 的目标机需要
fuse-exfat;内核 ≥ 5.4 的目标机只需要exfatprogs(甚至不装也能挂)。 - 目标机越“最小化”,越要把依赖下全(尤其
fuse-libs、fuse-common)。
4.2 方案 A:dnf download(RHEL 系,最推荐)
在一台与目标机同发行版大版本、同架构、已配好仓库的联网机上:
sudo dnf install -y dnf-plugins-core
mkdir -p ~/exfat-offline
# 关键:--resolve 解析依赖,--alldeps 连已安装的依赖也下载
# 这样目标机即使是最小化安装也不会缺 fuse-libs
dnf download --resolve --alldeps --destdir ~/exfat-offline \
fuse-exfat exfatprogs fuse fuse-libs fuse-common
要点:
- 只写
--resolve时,dnf 会跳过“当前联网机已安装”的依赖(例如fuse-libs),目标机若没装就会失败;建议加--alldeps。 - 目标机是其他架构时:
--forcearch=aarch64(要求仓库提供该架构的包)。 - 也可以改用下载后不安装的方式:
dnf install --downloadonly --downloaddir=$HOME/exfat-offline \
fuse-exfat exfatprogs fuse fuse-libs fuse-common
- 联网机没有 RPM Fusion 时先加仓库:
sudo dnf install -y epel-release
sudo dnf install -y \
https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm
- 导出 GPG 公钥(离线安装验签要用):
cp /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8 ~/exfat-offline/
cp /etc/pki/rpm-gpg/RPM-GPG-KEY-rpmfusion-free-el-8 ~/exfat-offline/
- 检查完整性:
cd ~/exfat-offline
for f in *.rpm; do rpm -K "$f"; done
rpm -qpR fuse-exfat-*.rpm | sort -u
4.3 方案 B:apt(Debian / Ubuntu)
在一台同发行版、同架构的联网机上:
sudo apt update
sudo apt install -y exfatprogs exfat-fuse
mkdir -p ~/exfat-offline
# 把包和依赖都下到指定目录(--reinstall 保证已安装的包也会重新下载)
sudo apt-get install --download-only --reinstall \
-o Dir::Cache::archives="$HOME/exfat-offline" \
exfatprogs exfat-fuse
说明:
- 不加
--reinstall时,已安装的包不会重新下载;用干净容器/虚拟机操作最稳。 - 更严格的离线方案可以用
apt-offline:在离线机生成签名清单,联网机按清单下载,再带回安装。 - aarch64 目标机需要对应架构的源,不能直接拿 amd64 的 .deb。
4.4 方案 C:直接从镜像站下 RPM(没有同发行版联网机时)
以 Anolis 8.6 / RHEL 8 x86_64 为例,本次实测可用的组合:
| 包 | 来源 | 示例地址 |
|---|---|---|
fuse-exfat-1.3.0-3.el8.x86_64.rpm |
RPM Fusion free EL8 | https://mirrors.ustc.edu.cn/rpmfusion/free/el/updates/8/x86_64/f/ |
exfatprogs-1.2.9-2.el8.x86_64.rpm |
EPEL 8 | 阿里云/清华 EPEL 镜像,或 dnf download |
fuse / fuse-libs / fuse-common |
Anolis BaseOS | Anolis 镜像的 BaseOS/x86_64/Packages/ |
下载后必须验签并检查依赖:
rpm -K fuse-exfat-*.rpm
rpm -qpR fuse-exfat-*.rpm
手动下载最容易漏依赖:fuse-exfat依赖libfuse.so.2(fuse-libs),fuse依赖fuse-common = 3.3.0。目标机没有就先补上。
4.5 包清单(按场景)
| 目标机 | 必装包 | 说明 |
|---|---|---|
| RHEL/Anolis 8(内核 4.18) | fuse-exfat + fuse-libs + fuse + fuse-common + exfatprogs |
FUSE 挂载 + 格式化/修复 |
| 内核 ≥ 5.4 的发行版 | exfatprogs(可选) |
挂载靠内核,工具用于 mkfs/fsck |
| Ubuntu/Debian 老内核 | exfat-fuse + exfatprogs(或 exfat-utils) |
FUSE 挂载 |
| 容器内使用 | 额外需要宿主机 /dev/fuse 和 SYS_ADMIN |
见第 7 节 |
4.6 打包
cd ~
tar czf exfat-offline.tar.gz exfat-offline/
sha256sum exfat-offline.tar.gz > exfat-offline.tar.gz.sha256
建议包内附:install.sh、README.md、SHA256SUMS、GPG 公钥。
5. 离线服务器安装
5.1 拷贝并校验
tar xzf exfat-offline.tar.gz
cd exfat-offline
sha256sum -c SHA256SUMS
5.2 导入公钥 + 本地安装
sudo rpm --import RPM-GPG-KEY-EPEL-8
sudo rpm --import RPM-GPG-KEY-rpmfusion-free-el-8
sudo dnf -y install --disablerepo='*' \
./fuse-common-*.rpm ./fuse-libs-*.rpm ./fuse-2*.rpm \
./fuse-exfat-*.rpm ./exfatprogs-*.rpm
说明:
--disablerepo='*'强制只从当前目录装,绝不访问网络仓库。- 目标机没有
dnf时退回 rpm:
sudo rpm -Uvh --replacepkgs \
./fuse-common-*.rpm ./fuse-libs-*.rpm ./fuse-2*.rpm \
./fuse-exfat-*.rpm ./exfatprogs-*.rpm
- 如果 GPG 校验失败,先确认公钥已导入;实在没有公钥才用
--nogpgcheck(不推荐)。
5.3 可选:搭本地仓库(多台离线机时)
sudo dnf install -y createrepo_c
sudo createrepo_c /opt/exfat-rpms
sudo tee /etc/yum.repos.d/exfat-local.repo >/dev/null <<'EOF'
[exfat-local]
name=exFAT local packages
baseurl=file:///opt/exfat-rpms
enabled=1
gpgcheck=0
EOF
sudo dnf install -y fuse-exfat exfatprogs
5.4 验证
rpm -q fuse-exfat exfatprogs
command -v mount.exfat mkfs.exfat fsck.exfat
用 128M 镜像做自测(不碰真实 U 盘):
dd if=/dev/zero of=/tmp/exfat-test.img bs=1M count=128
LOOP=$(losetup -f --show /tmp/exfat-test.img)
mkfs.exfat -n TEST "$LOOP"
mkdir -p /mnt/exfat-test
mount -t exfat "$LOOP" /mnt/exfat-test
echo hello > /mnt/exfat-test/hello.txt
sync
umount /mnt/exfat-test
mount -t exfat -o ro "$LOOP" /mnt/exfat-test
cat /mnt/exfat-test/hello.txt
umount /mnt/exfat-test
losetup -d "$LOOP"
rm -f /tmp/exfat-test.img
mount 显示 type fuseblk 即成功。
6. 挂载真实 U 盘与修复
# 1) 找设备
lsblk -o NAME,SIZE,TYPE,FSTYPE,LABEL,MOUNTPOINTS
# 2) 挂载
sudo mkdir -p /mnt/usb
sudo mount -t exfat -o uid=$(id -u),gid=$(id -g),umask=022 /dev/sdb1 /mnt/usb
# 必要时:
sudo mount.exfat -o uid=$(id -u),gid=$(id -g),umask=022 /dev/sdb1 /mnt/usb
# 3) 使用后安全卸载
sync
sudo umount /mnt/usb
修复脏卷(Windows 快速启动、直接拔盘导致):
sudo fsck.exfat -y /dev/sdb1
# 老 exfat-utils 用:sudo exfatfsck /dev/sdb1
格式化(会清空数据):
sudo mkfs.exfat -n MYUSB /dev/sdb1
7. 常见问题速查
| 现象 | 根因 | 处理 |
|---|---|---|
module exfat not found |
内核 < 5.4 或未编该模块 | 预期现象;装 fuse-exfat,不要死磕 modprobe |
unknown filesystem type 'exfat' |
没有内核驱动,也没有 FUSE 挂载器 | 装 fuse-exfat;或 sudo mount.exfat ... |
wrong fs type, bad option, bad superblock |
挂了整盘/挂错分区、VBR 损坏、脏卷 | lsblk 确认分区;dmesg;fsck.exfat |
blkid 没有 TYPE |
不是 exFAT、VBR 损坏、blkid 太老 | hexdump 看 EXFAT 标识;升级 util-linux |
| 挂载后只读 | 脏标志(快速启动/未安全弹出) | 备份后 fsck.exfat -y 再重挂 |
fusermount: mount failed: Operation not permitted |
容器缺 /dev/fuse 或 SYS_ADMIN |
宿主机挂载,或容器加 --device /dev/fuse --cap-add SYS_ADMIN |
fuse-exfat 在 EPEL 8 找不到 |
EPEL 8 不提供它 | 用 RPM Fusion free EL8 |
dnf download 漏依赖 |
只用了 --resolve,已安装依赖被跳过 |
加 --alldeps |
| GPG 校验失败 | 没导入 RPM Fusion/EPEL 公钥 | rpm --import 对应 KEY |
| 包装不上,提示架构不符 | 离线机是 aarch64,包是 x86_64 | 按目标架构重新下载 |
| 中文文件名乱码 | locale 非 UTF-8 | 设置 LANG=*.UTF-8;FUSE 版默认 UTF-8 |
无分区表挂不上 /dev/sdb1 |
U 盘整盘格式化(superfloppy) | 挂 /dev/sdb 本身 |
8. 本次实测记录
- 环境:Anolis OS 8.6,内核
4.18.0-372.16.1.an8_6.x86_64,x86_64。 - 安装:
fuse-exfat-1.3.0-3.el8+exfatprogs-1.2.9-2.el8,依赖fuse-2.9.7-19.1/fuse-libs-2.9.7-19.1/fuse-common-3.3.0-19.1。 - 测试:128M 镜像
mkfs.exfat→mount -t exfat(显示fuseblk)→ 写 8MB 随机文件 → sha256 校验 → 卸载后只读重挂校验一致 → 通过。 - 离线包:
exfat-offline-el8-x86_64.tar.gz,SHA2569d9a1e99be99635d52edcca42f573f2b56684d76eebf7ba1ede0adfc8309bcd3。
9. 最小步骤清单(TL;DR)
联网机(RHEL/Anolis 8,内核 4.18):
sudo dnf install -y epel-release
sudo dnf install -y https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm
dnf download --resolve --alldeps --destdir ~/exfat-offline \
fuse-exfat exfatprogs fuse fuse-libs fuse-common
cp /etc/pki/rpm-gpg/RPM-GPG-KEY-{EPEL-8,rpmfusion-free-el-8} ~/exfat-offline/
tar czf exfat-offline.tar.gz exfat-offline/
离线机:
tar xzf exfat-offline.tar.gz && cd exfat-offline
sudo rpm --import RPM-GPG-KEY-EPEL-8
sudo rpm --import RPM-GPG-KEY-rpmfusion-free-el-8
sudo dnf -y install --disablerepo='*' ./*.rpm
sudo mount.exfat -o uid=$(id -u),gid=$(id -g),umask=022 /dev/sdb1 /mnt/usb
川公网安备51010802033276号