Linux字体安装与fontconfig(fc)管理

Linux桌面/服务端字体统一由 fontconfig 框架管理,核心三件套:

fc-cache   → 生成/刷新字体缓存索引
fc-list    → 查询已安装字体
fc-match   → 匹配某个需求最接近的字体
fc-scan    → 扫描单个字体文件

底层机制:所有字体文件放指定目录 → fc-cache 扫描建索引(XML 缓存) → 应用通过 fontconfig 按名称/家族/风格找字体 → 找不到就回退(fallback)。


1.字体存放目录

目录                          级别     放什么
────────────────────────────  ───────  ────────────────────────────────────
/usr/share/fonts/            系统级    包管理器装的字体(package)
  ├── truetype/            系统级    TrueType (.ttf/.ttc)
  ├── opentype/            系统级    OpenType (.otf/.ttc)
  ├── type1/               系统级    Type1 (.pfa/.pfb)
  └── misc/                系统级    杂项
/usr/local/share/fonts/     管理员级  手动安装、第三方字体
~/.local/share/fonts/      用户级    个人字体(不影响他人)
  或 ~/.fonts/             用户级    旧版位置(部分发行版兼容)

查找优先级:用户级 > 管理员级 > 系统级(同名家族时用户目录优先)。


2.安装字体的完整流程

2.1放字体文件

1
2
3
4
5
6
7
8
9
10
# 系统级(需 root)
sudo cp /path/to/SourceHanSans.ttc /usr/share/fonts/truetype/

# 管理员级(需 root,适合"装给这台机器所有用户")
sudo mkdir -p /usr/local/share/fonts/myfont
sudo cp /path/to/*.ttf /usr/local/share/fonts/myfont/

# 用户级(普通用户即可)
mkdir -p ~/.local/share/fonts
cp /path/to/*.ttf ~/.local/share/fonts/

字体扩展名速查:.ttf(TrueType)、.otf(OpenType)、.ttc(TrueType Collection,一个文件含多个字重/变体)、.dfont(macOS 格式,Linux 不认)

2.2刷新缓存

1
2
3
4
5
6
7
8
9
# 普通用户(只刷用户级目录)
fc-cache -fv
# -f: 强制刷新(即使缓存未过期)
# -v: 显示扫描了哪些文件(verbose)

# 系统级(需 root,刷 /usr/share/fonts 和 /usr/local/share/fonts)
sudo fc-cache -fv
# 或指定目录
sudo fc-cache -fv /usr/local/share/fonts/myfont

不用刷缓存的后果:字体文件在了,但应用找不到(因为索引没更新),显示方块/回退默认字体。

2.3验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 按家族名查(最常见的用法)
fc-list | grep -i "Source Han"
# 输出: /usr/share/fonts/truetype/sourcehan/SourceHanSansCN-Regular.ttf: Source Han Sans CN:style=Regular

# 按文件路径查
fc-list /usr/share/fonts/truetype/sourcehan/

# 按编码查(确认中文字体是否注册了 CJK)
fc-list :lang=zh # 列出所有能显示中文的字体
fc-list :lang=ja # 日文
fc-list :lang=ko # 韩文
fc-list :lang=th # 泰文

# 按样式查
fc-list | grep "monospace" # 等宽字体
fc-list | grep -i "bold" # 粗体

3.fc-list选项速查

1
2
3
4
5
6
7
8
9
10
11
12
选项/参数              作用
───────────────────── ────────────────────────────────────────────────
fc-list [pattern] 按过滤模式查字体
fc-list :family 只打印家族名(去重前)
fc-list :style 只打印样式名
fc-list :file 只打印文件路径
fc-list :index 只显示当前索引号
fc-list :lang=xx 按语言过滤
fc-list :spacing=N 按间距类型(100=monospace, 124=proportional)
fc-list -s 显示每个 font 的所有 face(详细)
fc-list -v 超级详细(每个属性)
fc-list 文件路径 只扫描指定文件/目录

过滤模式语法(最常用):

1
2
3
4
5
6
7
8
9
10
# 基本格式: 属性=值  属性=值
fc-list :family="DejaVu Sans"
fc-list :family="DejaVu Sans":style=Bold
fc-list :spacing=100 # 所有等宽字体
fc-list :family="Source Han Sans CN":style=Regular:lang=zh
fc-list :size=12 # 所有12pt的(通常无意义, 字体一般不指定size)

# 通配
fc-list :family="*Mono*" # 所有名字含 Mono 的
fc-list :lang="*CJK*" # 所有 CJK 字体

4.fc-cache详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 基本用法
fc-cache [-svfo] [文件/目录...]
# 无参数 → 刷新默认所有目录

# 常用组合
fc-cache -fv # 强制 + 详细(最常用, 装完字体跑这句)
sudo fc-cache -fv # 系统级刷新
fc-cache -fv ~/.local/share/fonts # 只刷个人目录

# 查看缓存文件位置和状态
ls -la ~/.cache/fontconfig/ # 用户级缓存(默认在这)
ls -la /var/cache/fontconfig/ # 系统级缓存
# 典型文件: *.cache-* (编号递增, 如 cache-16 等)

# 删除缓存让系统重建(排错用)
sudo rm /var/cache/fontconfig/*.cache-*
rm -f ~/.cache/fontconfig/*.cache-*
sudo fc-cache -fv # 重建

缓存机制细节:

• 字体文件mtime变了 → 下次fc-cache才重建(不会自动)所以: 装完字体必须手动跑一次 fc-cache
• systemd环境下 /usr/share/fonts 由fontconfig的fc-cache.timer/timer
  自动管理(部分发行版); 但/usr/local/share/fonts通常要手动

5.查看当前生效配置

1
2
3
4
5
6
7
8
9
10
11
12
# 列出 fontconfig 用到的所有配置文件
fc-list --verbose | head -50
cat /etc/fonts/fonts.conf # 系统级主配置
cat /etc/fonts/conf.d/*.conf # 规则文件(数字前缀=加载顺序)

# 查看 fontconfig 搜索路径
fc-match -v "sans-serif" # 看它最终匹配到哪个字体
echo $XDG_CACHE_HOME # 缓存目录(默认 ~/.cache)
echo $XDG_CONFIG_HOME # 配置目录(默认 ~/.config)

# 查看 fontconfig 环境变量覆盖
env | grep FONTCONFIG # 如 FONTCONFIG_PATH/FONTCONFIG_FILES

/etc/fonts/conf.d/ 典型内容:

05-reset-dpi.conf               # 高DPI屏幕放大
10-hinting-full.conf            # 提示(hinting)级别
11-lcdfilter-default.conf       # LCD 子像素渲染
25-uni-silver-*.conf            # 某字体替换规则
30-aliases-*.conf               # 字体别名
51-locale-fix.conf              # 按 locale 选字体
65-nonospace-if-no-ttf-fonts... # fallback 规则
90-synopsis.conf

6.中文字体安装实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ═══ Ubuntu/Debian ═══
# 方案1: 直接装包
sudo apt install fonts-noto-cjk # Google Noto CJK(含中日韩)
sudo apt install fonts-wqy-zenhei # 文泉驿正黑
sudo apt install fonts-wqy-microhei # 文泉驿微米黑
sudo apt install fonts-droid-fallback # 兜底字体

# 方案2: 手动装(如思源黑体)
mkdir -p /usr/local/share/fonts/sourcehan
cp SourceHanSansCN-Regular.ttf /usr/local/share/fonts/sourcehan/
sudo fc-cache -fv
fc-list | grep "Source Han" # 验证

# ═══ RHEL/CentOS/Rocky ═══
sudo dnf install google-noto-sans-cjk-fonts # Noto
sudo dnf install wqy-zenhei-fonts # 文泉驿
sudo dnf install adobe-source-han-sans-fonts # 思源黑体(部分源)

# 验证
fc-list :lang=zh | head -5
fc-match "Source Han Sans CN" # 看匹配结果

验证中文字体能用的完整流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 文件在不在
ls /usr/share/fonts/**/*CJK* /usr/local/share/fonts/**/*CJK* 2>/dev/null

# 2. 缓存刷没刷
sudo fc-cache -fv

# 3. 注册没注册
fc-list :lang=zh | wc -l # >0 说明有中文可用字体
fc-list :lang=zh # 看具体哪些

# 4. 应用里能不能用
# GTK 应用:
env GTK_IM_MODULE=ibus gtk3-widget-factory & # 字体渲染预览
# 或装个 fc-browser 类工具直接看
# 终端: 装个等宽中文字体, 改 ~/.bashrc 的 TERM 或终端设置

7.字体替换/别名

有些软件要求特定字体名(如 Java AWT 要求 “Arial”,但 Linux 没有),可以建别名:

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
# 写一个 fontconfig 规则文件: /etc/fonts/local.conf (或 conf.d/99-myalias.conf)
cat > /etc/fonts/conf.d/99-myalias.conf <<'EOF'
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<!-- Arial → 替代为 Noto Sans (最接近的无衬线字体) -->
<match target="pattern">
<test qual="any" name="family"><string>Arial</string></test>
<edit name="family" mode="prepend" target="scope">
<string>Noto Sans</string>
</edit>
</match>

<!-- Times New Roman → Noto Serif -->
<match target="pattern">
<test qual="any" name="family"><string>Times New Roman</string></test>
<edit name="family" mode="prepend" target="scope">
<string>Noto Serif</string>
</edit>
</match>
</fontconfig>
EOF

sudo fc-cache -fv
fc-match "Arial" # 验证: 应返回 Noto Sans

Java 应用特有的字体问题(你的 Spring Boot 项目相关):

1
2
3
4
5
6
7
8
9
# Java AWT/Swing 用自己的字体查找, 不读 fontconfig
# 需要装包 + 配置:
sudo apt install fontconfig libfreetype6 # Java 底层的字体支持
# 若仍缺: 把 .ttf 放到 JRE 的 lib/fonts/ (Java 8 及以前)
# 或 /usr/share/fonts/ 即可 (Java 9+ 走 fontconfig)
# 验证:
java -fc-list # 不存在的命令(示意); 实际:
java -cp . TestFont | grep -i "Source"
# 或看 JVM 日志: -Dsun.java2d.font=fontconfig

Docker 里装字体的典型 Dockerfile片段:

1
2
3
4
5
6
7
8
9
10
FROM ubuntu:24.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
fontconfig \
fonts-noto-cjk \
ttf-dejavu \
&& rm -rf /var/lib/apt/lists/*
# 容器里 fc-cache 会自动跑(apt 的 postinst 钩子)
# 验证:
RUN fc-list :lang=zh | head -3

8.速查命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 装完字体后的标准三连
sudo fc-cache -fv
fc-list | grep -i "关键词"
fc-match "字体名"

# 查看所有可用字体家族(去重排序)
fc-list :family | sort -u

# 查看某个字体家族的所有变体
fc-list "Source Han Sans CN"

# 查看中文字体是否够
fc-list :lang=zh | wc -l

# 清除全部缓存重建
sudo rm -f /var/cache/fontconfig/*.cache-*
sudo fc-cache -fv

# 扫单个文件看元数据
fc-scan -v /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf

# 查看字体匹配链(为什么匹配到了某个字体)
fc-match -s "sans-serif" | head -20