资讯动态

LaTeX中文字体缺失报错排查:FangSong_GB2312找不到的完整解决方案

发布时间:2026/9/9 9:31:22 来源:尧图企业网站定制
这两天在帮一个项目组调LaTeX编译流水线结果一跑到文档编译那步就挂日志里明晃晃一行!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! fontspec error: font-not-found ! ! The font FangSong_GB2312 cannot be found. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!这个报错在texlive2025环境里太典型了尤其是在Linux服务器、WSL或者Docker容器里编译带中文的文档时。Windows上跑得好好的项目一挪到Linux就炸十有八九都是字体问题。我这几年踩过的坑从挖fontconfig配置到手动改字体名基本都集中在这条报错上。这篇文章就完整梳理一下FangSong_GB2312到底是什么为什么texlive找不到它以及在不同场景下怎么彻底解决。不管你是刚接触LaTeX的新手还是被CI构建折磨的运维又或者是写毕业论文被模板坑过的人这篇都能给你一套能直接抄的解决方案。1. 先别急着改代码弄懂FangSong_GB2312到底去哪了1.1 公文排版和论文模板为什么非要FangSong_GB2312先说字体本身。仿宋_GB2312是汉字排版里的老熟人国内党政机关公文格式要求正文用仿宋_GB2312高校毕业论文模板里也大量出现这个字体名。它的罗马化字体族名通常写作FangSong_GB2312在Windows系统里经常以“仿宋_GB2312”这个名字出现在字体列表中。这里有个特别容易搞混的点Windows系统自带的“仿宋”字体字体族名是FangSong文件名是simfang.ttf这个是系统自带的而“仿宋_GB2312”字体族名是FangSong_GB2312它往往不是Win系统默认自带的很多是跟着Office套件或者用户自己安装进去的。这俩是两套不同的字体字形细节和字库范围都有差异。很多人在Linux上装了个simfang.ttf以为问题解决了结果LaTeX还是报cannot find FangSong_GB2312就是因为实际装错了字体。在LaTeX文档里这个字体名出现的典型方式有两种% 方式一ctex宏包配合fontsetwindows时部分模板会显式覆盖字体 \documentclass[fontsetwindows]{ctexart} \setCJKmainfont{FangSong_GB2312} % 方式二直接用fontspec/xeCJK声明 \usepackage{xeCJK} \setCJKmainfont{FangSong_GB2312}问题就出在这当你用xelatex或lualatex编译时引擎不会自己去扫描字体文件而是通过系统的字体服务Linux/macOS上是fontconfigWindows上是DirectWrite来查找字体。查不到这个字体名就直接抛异常退出报错信息就是cannot find FangSong_GB2312。1.2 为什么Windows编译正常、Linux/WSL上就报错核心原因很简单字体不是跨平台的。Windows字体是Windows的Linux系统默认不会给你装任何Windows专有字体。texlive2025自带的中文字体是Fandol系列FandolSong、FandolHei、FandolKai、FandolFang和Arphic系列这些是开源字体覆盖了宋、黑、楷、仿四类基本书体但字体名里没有FangSong_GB2312。所以只要文档里写了\setCJKmainfont{FangSong_GB2312}编译时fontconfig就会去字体库里找这个名字。找不到报错结束。这个过程不区分你用的是texlive2023还是texlive2025也不管你的LaTeX宏包是不是最新版——字体查找是引擎层面的行为跟LaTeX版本关系不大。我把常见平台的默认情况整理成了一张表平台是否自带FangSong_GB2312常见自带仿宋字体说明Windows本机已安装字体部分有FangSong仿宋、仿宋_GB2312能否编译取决于到底装没装过“仿宋_GB2312”Windows纯净系统不一定FangSong仿宋如果模板里写的是FangSong_GB2312可能也会报错LinuxUbuntu/Debian/CentOS无无texlive自带FandolFang但名字不同WSL默认配置无无WSL默认不加载Windows字体需要额外配置macOS无STFangsong华文仿宋字体名完全不同需要映射或改名Docker容器无无需要额外安装字体包或COPY字体镜像这也是为什么同一个项目在不同人电脑上编译结果天差地别的原因。1.3 ctex的fontset机制自动选择不等于万事大吉ctex宏包提供了一个fontset参数可以指定从哪套字体配置里取字。比如\documentclass[fontsetwindows]{ctexart} % 使用Windows字体 \documentclass[fontsetfandol]{ctexart} % 使用Fandol开源字体 \documentclass[fontsetmac]{ctexart} % 使用macOS华文字体如果不显式指定ctex 2.x会根据当前操作系统自动推断在Windows上用SimSun那一套在macOS上找华文字体在Linux上用Fandol。理论上这样设计很智能但问题在于很多老模板里会同时手动覆盖\setCJKmainfont把字体写死成FangSong_GB2312。一旦模板里写了这种硬编码ctex的fontset再怎么自动选择也白搭——你手动声明的字体会覆盖掉ctex的默认配置。所以排查这个报错的时候第一件事不是急着装字体而是先搞清楚这个字体名到底是在哪里被声明的。是文档导言区显式写的还是模板.cls文件里写的又或者是从ctex的某个fontset配置里带出来的。定位源头的思路不同后续处理方式完全不同。2. 排查不是瞎猜三个命令定位问题2.1 先确认你的编译引擎和字体配置来源在动手修之前先把问题范围缩小。我的习惯是分三步走确认编译引擎打开项目看是用xelatex还是lualatex编译。字体查找机制的入口不同但最终都落在fontconfig上。用latexmk的话可以看下latexmkrc文件里配置的是xelatex还是lualatex。打开文档源码或模板.cls文件全局搜索一下“FangSong_GB2312”这个字符串看它出现在哪里。这一步能直接告诉你问题源头。把编译命令完整跑一遍确保报错确实是字体错误而不是其他宏包错误。有时候前提搞错了后面全是白费功夫。在我见过的项目里90%的情况是模板.cls文件里硬编码了\setCJKmainfont{FangSong_GB2312}剩下10%是用户自己写的导言区。2.2 用fc-list确认系统里到底有没有这个字体在Linux或WSL终端里跑这个命令fc-list :langzh这条命令会列出系统里所有支持中文的字体。输出里会包含字体文件路径、字体族名中英文、样式等信息。如果系统里装了仿宋相关的字体你多半能在输出里看到类似这样的行/usr/share/fonts/truetype/fangsong/simfang.ttf: 仿宋,FangSong:styleRegular注意看冒号后面的是字体族名。如果有FangSong但没FangSong_GB2312那说明你或系统安装的是“仿宋”而不是“仿宋_GB2312”。如果连仿宋的影子都没有那就更直接了——系统里根本没有对应的字体。再精确验证一下fc-match FangSong_GB2312如果fontconfig里能找到这个字体fc-match会输出字体文件路径比如/usr/share/fonts/truetype/custom/FangSong_GB2312.ttf: 仿宋_GB2312,FangSong_GB2312:styleRegular如果找不到fc-match会输出一个空行或一个替代字体的路径fallback结果。这也能侧面说明LaTeX报cannot find FangSong_GB2312是完全正常的——系统层面就不存在这个字体。2.3 字体存在但LaTeX还是找不到排查字体名的不一致还有一种情况比较隐蔽字体文件装好了fc-list也能看到了但LaTeX编译还是报找不到。这多半是字体名不一致的问题。Linux上安装的字体如果字体文件内部的family name是中文字段“仿宋_GB2312”那么fc-list里显示的主名可能是中文“仿宋_GB2312”而罗马化的“FangSong_GB2312”可能只作为别名出现甚至完全没有。xelatex在匹配字体名时对中文名和英文名的处理策略不完全一样有时候你写中文名能匹配上写英文名就匹配不上。判断方法是用fc-scan查看字体文件的详细信息fc-scan /usr/share/fonts/truetype/custom/FangSong_GB2312.ttf输出里会有family和fullname字段能直观看到字体的真实名字。如果family是“仿宋_GB2312”而没有包含FangSong_GB2312这个别名那你在文档里写\setCJKmainfont{FangSong_GB2312}就可能认不出来这时需要改成\setCJKmainfont{仿宋_GB2312}中文名来试。这一步排查很重要很多人栽在这个细节上以为装好了字体就应该万事大吉结果卡在名字匹配上几个小时。3. 四种解决方案从改系统到改模板3.1 方案一把字体装进系统治本如果项目必须用FangSong_GB2312这个字体且你不能改模板那最可靠的做法就是把字体装进系统里。字体来源从有FangSong_GB2312的Windows机器上将字体文件复制出来。注意版权问题这种字体的使用许可通常不允许随意分发但个人项目、公司内网使用一般问题不大不能用于商业再分发。拿到字体文件后在Linux上安装到用户目录即可不需要sudomkdir -p ~/.fonts cp FangSong_GB2312.ttf ~/.fonts/ fc-cache -fv ~/.fonts如果想装到系统全局给所有用户使用sudo mkdir -p /usr/share/fonts/truetype/custom sudo cp FangSong_GB2312.ttf /usr/share/fonts/truetype/custom/ sudo fc-cache -fv装完验证fc-list | grep -i fangsong看到FangSong_GB2312出现在输出里再重新编译LaTeX文档应该就不会报这个错了。这里有个重要提醒如果你复制的是Windows自带的simfang.ttf那只是“仿宋”FangSong不是“仿宋_GB2312”。必须确认字体文件对应的family name真的是FangSong_GB2312用fc-scan看清否则装完还是会报错。3.2 方案二改用texlive自带的Fandol字体省事如果不强制要求“仿宋_GB2312”这个字体只是需要一份仿宋风格的中文正文那最省事的办法是改用Fandol字体。texlive2025本身就带了Fandol系列无需额外安装任何字体。改法很简单把文档导言区的字体声明改成\documentclass[fontsetfandol]{ctexart}如果之前没有用ctex文档类而是手动写的字体配置那把\setCJKmainfont的参数改掉\usepackage{xeCJK} \setCJKmainfont{FandolFang}FandolFang是Fandol系列的仿宋体字形规整排版效果和仿宋_GB2312其实很接近。至少从“正文是仿宋风格”这个需求上讲FandolFang完全够用。这个方案的优点是零依赖、部署简单CI环境里不用有额外字体也能编译。缺点也很明显如果是一个严格要求“仿宋_GB2312”字形的公文或学校模板FandolFang的笔画细节和GB2312标准字库还是有差异的在一些笔画结构上能看出区别。如果你只是想让编译通过不在乎字体严格一致这个方案性价比最高。3.3 方案三把字体文件放进项目目录迁移友好如果既不想改模板又不想动系统字体还有一个折中方案把字体文件放在项目目录下通过fontspec的Path参数指定字体路径。项目结构示例project/ ├── main.tex ├── fonts/ │ └── FangSong_GB2312.ttf └── compile.sh文档里这样写\usepackage{xeCJK} \setCJKmainfont{FangSong_GB2312}[ Path ./fonts/ , Extension .ttf , UprightFont FangSong_GB2312 , BoldFont FangSong_GB2312 ]这样编译时xelatex会直接去指定目录找字体文件而不依赖系统字体库。好处是项目自包含换机器clone后直接编译就能过不需要额外装字体。坏处是如果文档里很多地方用到这个字体每处都要写Path参数比较啰嗦而且改路径时文件层级变了容易出错。另外一个变体也可以不指定Path而是把字体文件放到texlive的字体搜索路径里比如texmf-local目录。但这样做维护成本高不如直接在项目里指定路径来得直观。3.4 方案四WSL里让fontconfig直接识别Windows字体如果你用的是WSLWindows Subsystem for Linux还有一个独特的手段让WSL里的fontconfig直接读取Windows字体目录。Windows字体在WSL里通常挂载在/mnt/c/Windows/Fonts。创建或编辑fontconfig配置文件mkdir -p ~/.config/fontconfig cat ~/.config/fontconfig/fonts.conf EOF ?xml version1.0? !DOCTYPE fontconfig SYSTEM fonts.dtd fontconfig dir/mnt/c/Windows/Fonts/dir /fontconfig EOF然后刷新缓存fc-cache -fv执行完后再用fc-list验证fc-list | grep -i fangsong如果Windows系统里装了仿宋_GB2312字体这时WSL里就能直接看到它了。这个方案的优点是完全不用复制字体文件WSL和Windows共享字体缺点是走/mnt/c的I/O效率较低大量字体加载时会稍慢另外如果后续把编译环境从WSL迁到纯Linux服务器这套配置就失效了。我个人的使用建议WSL里调试阶段可以用这个方案快速验证但最终要上CI/服务器时还是走方案一或方案三更稳。4. 实操记录一次完整的Linux服务器LaTeX编译修复4.1 报错现场还原事情是这样的一个论文模板项目在Windows本机用TeXstudio编译一切正常。代码推到GitLab后CI用流水线执行编译结果在那台Ubuntu 22.04的构建机上直接挂了。日志片段长这样Executing command: xelatex -interactionnonstopmode -halt-on-error main.tex ... Package fontspec Error: The font FangSong_GB2312 cannot be found.项目里用的是ctexart文档类导言区长这样\documentclass[fontsetwindows]{ctexart} \setCJKmainfont{FangSong_GB2312} \setCJKsansfont{SimHei} \setCJKmonofont{KaiTi}问题很清楚fontsetwindows要求系统里有Windows字体但构建机是干净的Ubuntu什么都没装。而且模板里硬编码了FangSong_GB2312所以ctex的自动回退机制也失效了。4.2 修复步骤我用的是“模板改Fandol 项目内字体文件兜底”的双保险策略这样既解决当前编译又避免以后换机器还踩同样的坑。第一步先在服务器上确认texlive2025已装好xelatex可用which xelatex xelatex --version | head -n 1第二步检查系统里有没有中文字体fc-list :langzh输出是空的果然一个中文字体都没装。这时候如果直接用Fandol理论上不需要额外装字体——texlive自带。但保险起见我还是安排了一个字体文件放入项目目录方便将来有需求时直接调用。第三步修改模板文件的字体配置。把导言区改为\documentclass[fontsetfandol]{ctexart}同时把所有\setCJKmainfont{FangSong_GB2312}这样显式指定字体的行注释掉或改成%\setCJKmainfont{FangSong_GB2312} \setCJKmainfont{FandolFang}并把\setCJKsansfont{SimHei}改成FandolHei\setCJKmonofont{KaiTi}改成FandolKai。第四步重新编译latexmk -xelatex -halt-on-error main.tex编译通过PDF正常生成内容和Windows上编译的版式几乎无差别。4.3 如果要强行保留FangSong_GB2312呢如果模板不能改那就在构建机上装字体。我在另一台测试机上试过完整流程sudo mkdir -p /usr/share/fonts/truetype/custom sudo cp FangSong_GB2312.ttf /usr/share/fonts/truetype/custom/ sudo fc-cache -fv fc-match FangSong_GB2312输出显示匹配到了字体文件后直接latexmk编译同样通过不再报cannot find。这里我的建议是如果项目逻辑允许改模板优先用Fandol方案因为部署成本为零还不用处理字体版权分发问题。如果必须用原字体那就老老实实在服务器上装字体并且把字体文件放到CI的构建配置里一起管理不要指望每次构建时手工操作。5. 你可能还会遇到的五个坑5.1 字体装好了但LaTeX还是报找不到如果你用的是lualatex编译它有自己的字体缓存luaotfload跟fontconfig是两层。装了新字体后lualatex不一定能立刻识别。解决办法是清缓存重建luaotfload-tool --clear-cache luaotfload-tool --update-cache清完再编译通常就能找到了。这个问题在xelatex里基本不会遇到xelatex走的是fontconfig实时读取。5.2 字体名对不上中文名vs英文名再强调一次Linux上安装字体后字体在fc-list里显示的名字可能和Windows注册名不一样。上面提到过用fc-scan查看实际名称fc-scan FangSong_GB2312.ttf | grep -E family|fullname如果family是“仿宋_GB2312”没有FangSong_GB2312别名那在文档里可以这么写\setCJKmainfont{仿宋_GB2312}不过这个写法在不同系统和字体配置下兼容性略差能想办法补充字体别名最好。比较稳妥的做法是用FontForge等工具修改字体文件的family name加一个FangSong_GB2312的别名。但这样做会改变字体文件指纹一般人不建议折腾。我的经验就是先试文档里写中文名能跑通就不用折腾跑不通再考虑改字体元数据。5.3 模板里除了仿宋_GB2312还有楷体_GB2312等一整套GB字体这类模板一般不止用仿宋_GB2312一种字体往往还有黑体、楷体、宋体的一整套GB2312系列。在Linux上想全套装齐最好一次性处理掉。常见需要的有字体名用途对应Linux替代仿宋_GB2312正文FandolFang楷体_GB2312二级标题、引文FandolKai黑体SimHei一级标题FandolHei宋体SimSun部分模板正文FandolSong如果不想逐个复制Windows字体也可以直接考虑安装fonts-noto-cjk包然后手动把字体映射到GB2312字体名上但字形会不是仿宋风格一般不建议这么干。5.4 CI环境没有sudo权限怎么办很多CI Runner不会给你sudo。这时不能用/usr/share/fonts目录改为装到用户级目录mkdir -p ~/.fonts cp FangSong_GB2312.ttf ~/.fonts/ fc-cache -fv ~/.fonts如果连~/.fonts方案也不行比如Runner是容器每次构建环境都是全新的那就只能走方案三——把字体文件放进项目用Path指定。这是最保险的做法不依赖任何环境预装。5.5 Docker镜像里字体丢失问题Docker镜像默认只有极简字体连中文字体包都没有。建议在Dockerfile里直接安装字体包RUN apt-get update apt-get install -y fonts-noto-cjk \ rm -rf /var/lib/apt/lists/*如果必须用FangSong_GB2312就把字体COPY进镜像COPY FangSong_GB2312.ttf /usr/share/fonts/truetype/custom/ RUN fc-cache -fv还有一点Docker构建时如果用了多阶段构建要注意最终运行阶段里有没有把字体文件COPY过去。经常有人第一阶段装好了字体第二阶段换了基础镜像结果字体全没了编译照样失败。6. 写到最后的一点个人体会搞定了好几个项目的这个问题之后我最大的感受是字体问题看似简单背后的机制却串联了操作系统字体管理、文本渲染引擎、LaTeX字体配置三个层面。真正上手时不要一开始就想着“把字体装上”而是先弄清楚系统层面有没有这个字体、引擎是怎么找字体的、文档里是怎么声明的。把这三件事对齐了很多匪夷所思的报错会瞬间变得简单。另外如果是长期维护的项目我强烈建议把字体方案固化到项目配置里——要么明确用Fandol要么把字体文件和路径配置提交到仓库。千万不要依赖“我这台机器上有这个字体”这种隐式前提换环境时一定会出问题。CI环境里尤其如此能在构建配置里显式写明依赖的字体就能省下一堆半夜排查构建失败的痛苦。最后再分享一个小技巧如果你临时要在一台机器上快速判断问题是不是字体缺失其实不用一行行翻LaTeX日志。先fc-match那个报错里的字体名如果输出为空直接去看文档里是不是显式声明了这个字体——两个问题一确认根因就锁定了。剩下的事情就是选一种适合你场景的方案执行而已。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价