资讯详情

资讯详情

LaTeX报错rsfs5.tfm already exists:字体文件冲突的排查与修复

前一阵临时赶一篇带数学公式的中文稿编译时终端突然蹦出一行不太常规的报错/ctex/userdata/fonts/tfm/public/rsfs/rsfs5.tfm already exists刚看到的时候我也愣了一下。平时LaTeX报错大多是“未定义的控制序列”或者“文件找不到”突然来一句“文件已存在”确实容易让人摸不着头脑。仔细看了日志才发现这个报错跟正文语法几乎没关系问题出在字体文件管理上属于典型的文件冲突。这篇文章就是把这件事讲透这个报错从哪来、怎么排查、如何修好顺便把TeX排版系统里字体文件这一套机制说明白。如果你用的是TeX Live或MiKTeX或者用CTeX宏包编译中文文档又恰好被“already exists”这类提示卡过可以直接照着我后面的顺序走一遍大部分情况下不需要重装任何东西。1. 报错现场还原与问题定性1.1 一次典型的编译失败现场我当时的环境很普通XeLaTeX编译文档类用的是ctexart模板里定义了一些数学符号公式里恰好有\mathscr{F}这类命令。编译到一半终端输出的日志停在这样几行kpathsea: Running mktexmf rsfs5 mktexmf: The file rsfs5.tfm already exists. /ctex/userdata/fonts/tfm/public/rsfs/rsfs5.tfm already exists随后编译中断PDF没有正常生成。这里先说一个容易混淆的点这类提示不是LaTeX排版引擎本身的语法错误而是在“字体文件准备阶段”被拦下来的。TeX引擎在排版前需要拿到字体的度量信息而mktexmf这类工具负责在找不到字体时尝试生成或补全字体文件。生成过程中发现目标路径里已经有一个同名文件于是一边觉得“有文件可以用了”一边又不知道到底该信任哪个干脆抛出already exists中止操作。所以第一反应不应该是去改文档代码而是先判断这个错误到底是“重复安装导致冲突”还是“权限问题导致无法覆盖”还是“文件名数据库和实际磁盘状态不一致”。三条路对应完全不同的修法。1.2 拆解报错里的每个关键词把报错拆开看每个字段都是有意义的rsfs5RSFS字体系列中的一个字体度量文件编号。RSFS是数学书法体常用于排版\mathscr风格的字符。.tfmTeX Font Metric字体度量文件。它不包含字形轮廓只记录每个字符的宽度、高度、深度、斜度这些排版数据。字形本体在.pfb、.pk或.mf等文件里。/ctex/userdata/某个用户级texmf目录路径。看到userdata基本能确定这是用户本地数据目录可能是CTeX宏包初始化时创建的也可能是你手动放置字体时建立的。already exists目标文件已经存在写入操作被拦截。把这几个词拼起来问题本质就清楚了你在某一层texmf树里已经有一个rsfs5.tfm而系统在安装或生成字体时又试图往同一个路径写入同一个文件。要么是重复安装要么是文件归属混乱要么是权限不够导致无法覆盖旧文件。2. 为什么rsfs字体成了“背锅侠”2.1 rsfs字体到底是干什么用的RSFS字体全称直译过来是“正式手写体”是上世纪七十年代就设计出来的一套书法体数学符号字库。它解决的问题很简单数学排版里需要一些看起来像手写风格的符号比如傅里叶变换里的\mathscr{F}、拉普拉斯算子里的\mathscr{L}、泛函分析里的各种花体字母。在很多论文模板里宏包mathrsfs就是基于这套字体实现的。只要你文档里出现过\mathscr就会触发rsfs相关字体的加载。CTeX宏包处理中文文档时经常顺带排版数学公式所以这类字体冲突在中文LaTeX用户里并不少见。它的TFM文件为什么重要因为TeX排版机制和现在常见的“所见即所得”编辑器完全不一样。TeX把每一个字符当成一个小盒子排版前必须精确知道每个字符的宽高深斜度。TFM文件就是这套“排版尺”少了它字体加载立刻失败编译直接停下。所以rsfs5.tfm看起来是个不起眼的文件对最终产物却非常关键。2.2 CTeX、TFM与字体搜索链要理解already exists还必须知道TeX发行版是怎么找字体的。TeX Live、MiKTeX这类发行版会配置多个texmf目录树按优先级排列常见的有TEXMFHOME当前用户目录下的~/texmf用户手动放的字体、宏包通常放这里。TEXMFLOCAL本机共享目录通常由管理员维护。TEXMFDIST发行版自带的目录里面是宏包和字体原始文件。正常情况下查找路径是唯一的kpsewhich从这些目录按顺序找哪个找中了就用哪个。但字体安装和更新时工具会向这些目录写入文件。一旦用户手动复制、安装脚本又执行一次、或者升级TeX发行版时留下旧文件同一个rsfs5.tfm就可能出现在多个目录树里。说严重也不严重系统并不知道该用哪一份于是冲突就冒出来了。CTeX宏包在这个环节里的角色比较特殊它会按中文排版需求加载一系列字体和格式文件有时还会创建自己的userdata路径。如果用户之前手动装过某些字体包或者CTeX初始化时生成过一批字体文件之后再更新同一套字体自然会出现“两个同路径文件”的局面。2.3 already exists到底在哪个环节触发我自己见过的情况主要有三种排查方向不太一样。第一种mktexmf生成字体时触发。当你用的字体源文件存在但TFM缺失系统会自动尝试生成TFM生成前检查发现目标位置已有同名文件于是报错。这种情况多半是旧文件还在系统想重新生成但默认“不动已有文件”。第二种宏包安装或更新时触发。tlmgr install rsfs这类操作执行时安装脚本会把字体文件拷贝到目标目录如果目标目录里已经有一份旧版文件部分脚本会直接提示already exists。第三种权限问题被“包装”成了already exists。文件确实存在但当前用户没有写权限工具既不能覆盖又不能删除就把问题描述为“已存在”而不是“权限不足”。这也是我为什么强调先看完整日志。单看最后一行容易误判把前几行也贴出来找到到底是“生成”“安装”还是“权限”环节报错修复起来就快很多。3. 分场景排查与修复实操3.1 场景一文件名数据库没刷新或缓存异常判断条件很明确只有already exists提示日志里没有明显的权限相关单词而且文件本身能正常找到。这种场景下先别急着删文件先刷新文件名数据库。TeX系统依靠文件名数据库快速定位文件数据库与实际磁盘状态不一致时什么奇怪问题都可能出现。# TeX Live 环境刷新文件名数据库 sudo mktexlsr # 某些发行版也可以用 sudo texhash刷新完成后重新编译一次。如果报错还在可以顺带重建格式文件# 重建所有格式文件 sudo fmtutil-sys --allMiKTeX用户不用命令行也可以打开MiKTeX Console进入“Tasks”点击“Refresh file name database”。旧式CTeX套装里通常也有“Refresh”按钮。这一步做完很多“明明文件存在却还报错”的问题就消失了。3.2 场景二同一个字体在多个texmf树里重复这是最常见也最可能的原因。判断方法很简单# 确认当前搜索到的是哪个文件 kpsewhich rsfs5.tfm # 查找系统里所有同名文件 find $HOME -name rsfs5.tfm 2/dev/null find /usr/local/texlive -name rsfs5.tfm 2/dev/null如果kpsewhich返回了发行版自带路径比如/usr/local/texlive/.../texmf-dist/fonts/tfm/public/rsfs/rsfs5.tfm而find同时还发现~/texmf/fonts/tfm/public/rsfs/rsfs5.tfm或者那个/ctex/userdata/路径下也有一份问题就实锤了重复安装。处理原则很简单保留发行版或更新版本的那份把另一份移走而不是直接删除万一误判还能恢复。# 建议先建立备份目录 mkdir -p ~/tex_backup # 把用户目录下的重复文件移走 mv ~/texmf/fonts/tfm/public/rsfs/rsfs5.tfm ~/tex_backup/ # 刷新数据库 sudo mktexlsr这里有一个判断技巧如果kpsewhich rsfs5.tfm能返回路径说明系统已经能正常找到字体如果它返回为空才是真正的“字体缺失”。后者不应该手动复制而应该用包管理器安装# TeX Live 环境 tlmgr install rsfsMiKTeX用户更简单编译时如果缺字体它通常会弹窗提示自动安装或者打开MiKTeX Console手动安装对应宏包。3.3 场景三文件权限导致无法覆盖判断标志很直接报错信息里出现Permission denied、Not owner、Operation not permitted这些词或者你回忆自己之前用sudo复制过字体文件。先看文件归属ls -l /ctex/userdata/fonts/tfm/public/rsfs/rsfs5.tfm如果显示属主是root而你当前是普通用户后续工具想覆盖或生成新文件时就会失败。处理方式也直接# 将用户目录下字体的属主改为当前用户 sudo chown -R $(whoami) /ctex/userdata # 或者只调整写权限 sudo chmod -R uw /ctex/userdata这里提醒一句如果重复文件在TEXMFDIST这种发行版系统目录里不建议对一整个目录执行chown或chmod那会影响其他文件。正确做法是优先考虑用tlmgr修复宏包或者把字体放进自己的用户目录。系统目录交给系统管理用户字体放用户目录这个边界越清楚后续麻烦越少。3.4 场景四手动安装方式留下的冲突还有一种典型情况从网上下载了一个字体压缩包里面包含rsfs5.tfm按某篇教程的解压后直接丢到了texmf树里。这种做法不是不行但很容易遗漏目录结构的细节。TeX有自己约定的目录结构也就是TDSTeX Directory Structure。字体文件应该放在类似下面这样的相对路径下texmf/fonts/tfm/public/rsfs/rsfs5.tfm很多人图省事直接把文件解压到texmf/rsfs5.tfm系统找不到或者反复解压到不同层级出现了两个名字路径都可能命中的副本。这种冲突处理方式和场景二一致用find把所有副本找出来按照正确TDS路径保留一份其余移走刷新数据库。如果你想彻底避免这类问题最简单的办法就是不要手动安装字体。先试试包管理器包管理器没有的才考虑手动。手动装完第一件事就是mktexlsr把文件名数据库刷新到位。3.5 修复完成后的验证步骤修复之后不要急着欢呼用一条命令确认搜索结果唯一kpsewhich rsfs5.tfm正常输出应该是唯一的路径。如果还是能看到多个同名文件继续清理。然后写一个最小测试文档验证rsfs字体确实能正常加载\documentclass{ctexart} \usepackage{mathrsfs} \begin{document} \[ \mathscr{F}(f)(\xi) \int_{-\infty}^{\infty} f(t)e^{-2\pi i t \xi}\,\mathrm{d}t \] \end{document}用XeLaTeX编译这个文件能顺利出PDF说明rsfs字体已经彻底恢复。提示最小测试文档是最好的“诊断剂”。它能帮你区分是全局字体配置问题还是当前文档模板里的个别配置问题。如果把最小文档编译通过而原文档还是报错问题多半出在你自己的模板或宏包配置上。4. 避免下次再踩坑的目录结构建议4.1 把文件放到它该去的地方这次修完很多人过几个月还会遇到类似的“already exists”。原因很简单习惯没改。TeX字体文件在texmf树里是有明确分类的fonts/tfm字体度量文件fonts/type1Type1轮廓字体fonts/truetypeTTF字体fonts/opentypeOTF字体fonts/sourceMETAFONT源文件如果你确实需要手动安装某个字体应该在用户目录下建出这样的结构而不是随意在任意目录放文件~/texmf/ └── fonts/ └── tfm/ └── public/ └── rsfs/ └── rsfs5.tfm这样做的好处是文件名数据库刷新后kpsewhich能准确定位不会出现“系统里有两份搜索时不知道怎么选”的问题。反过来如果文件散落各处后续排查成本真的会被无限放大。4.2 更新TeX发行版前后的收尾动作升级TeX Live或者切换版本时最容易产生残留文件。旧版本的目录如果卸载不干净新版本安装时往同类路径写入同名文件就会撞出already exists。我的习惯是升级前先更新到当前最新状态sudo tlmgr update --self --all升级完成后跑一次sudo fmtutil-sys --all sudo mktexlsrMiKTeX的滚动更新机制通常不会出现这类冲突但如果你在用户目录手动放置过字体更新周期结束前最好也手动清一次TEXMFHOME里的旧副本。4.3 两条少走弯路的习惯第一遇到文件类报错先问三个问题这个文件从哪儿来谁需要它为什么同一个路径会存在多份把这三个问题弄明白比盲目搜“怎么解决”有效得多。第二不要往发行版系统目录里塞自己的文件。TEXMFDIST里的文件归包管理器管你手动塞进去下次升级可能就被覆盖或冲突。想让某个字体对全局生效正确位置是TEXMFLOCAL只想自己用放TEXMFHOME就够了。第三Windows环境下还有一个隐蔽坑多个编辑器同时打开同一个文档并编译可能造成文件占用报错表现也像already exists。这时先关掉其他编辑器进程比反复改权限有用。5. 常见报错变体速查表5.1 常见报错变体速查表不同发行版、不同编译方式下报错措辞会略有差异我把常见的变体整理成一个速查表方便对号入座现象可能原因推荐做法rsfs5.tfm already exists重复安装、手动复制、路径重复用kpsewhich和find找副本保留发行版一份其余移走刷新数据库Permission deniedrsfs5.tfm文件属主为root普通用户无法覆盖chown调整属主或把字体放到TEXMFHOMEFile rsfs5.tfm not found文件名数据库未刷新或rsfs包没安装mktexlsr如果仍未解决用tlmgr install rsfsFont \scrscr not loadableTFM缺失或损坏重新安装rsfs宏包重建格式文件mktexmf: rsfs5.mf already exists字体源文件重复找到重复的.mf文件清理后刷新数据库/ctex/userdata/...路径冲突CTeX用户数据目录与发行版重复检查userdata目录保留一份重建格式文件5.2 最后提醒动手前先说三遍“备份”讲一个我自己掉过坑的教训有一次我怀疑某个字体文件坏了直接rm删掉结果发现那是发行版自带的文件并且当前版本根本不含这个字体。最后只能重新安装相应当包花的时间比原本解决问题多得多。所以无论你判断多准都建议先把疑似重复的文件移到备份目录而不是彻底删除。备份目录可以是一个普通文件夹不用放在texmf树里。另外完整日志永远是第一排查资料。很多人报错时只贴最后一行这样很难定位。下次遇到这类问题把从kpathsea开始的那几行日志全部贴出来一看就知道是在生成字体、安装字体还是权限检查环节断掉的。按照上面的顺序走绝大多数already exists都能在十分钟内解决。它本质上不是高深问题只是告诉你有两份一样的钥匙你只需要把其中一把放到该放的地方然后让系统重新认识一遍文件就够了。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →