首页 / 资讯中心 / 文章详情

TeX Live 2020下pdflatex.fmt文件丢失的排查与修复

TeX Live 2020下pdflatex.fmt文件丢失的排查与修复 ★ FEATURED ARTICLE
早上刚坐下准备编译手头一篇文档终端里直接甩出一句kpathsea: Running mktexfmt pdflatex.fmt I cant find the format file pdflatex.fmt!说实话这种报错很容易让人血压上来。界面干净没有任何多余提示好像整个TeX系统一夜之间罢工了。但以我在TeX Live系列上踩过的坑来说这个错误十有八九不是TeX本身坏了而是环境没配对、文件没生成、或者权限不给力。这篇文章就围绕TeX Live 2020下的这个经典报错把排查思路、背后机制、各平台差异完整拆一遍希望给遇到同样问题的人一条能直接照做的路径。1. 报错背后的机制fmt文件是怎么丢的1.1 格式文件在TeX中扮演什么角色先别急着敲命令弄清楚pdflatex.fmt是什么排查起来会事半功倍。.fmt是TeX引擎的格式文件可以理解成一份“预编译好的宏包快照”。TeX引擎在启动时如果每次都要现场读入plain.tex、再读入LaTeX内核所有宏包定义生成慢是小事重复劳动才是大问题。所以系统在安装或升级时会把“pdfTeX引擎 LaTeX kernel”编译后的状态固化成pdflatex.fmt启动时直接载入这份快照几秒钟就能进入到能编译正文的状态。这个文件在TeX Live中的位置有讲究。发行树下面的标准路径通常是/usr/local/texlive/2020/texmf-var/web2c/pdftex/pdflatex.fmtWindows下则类似D:\texlive\2020\texmf-var\web2c\pdftex\pdflatex.fmt用户目录下也可能出现~/.texlive2020/texmf-var/web2c/pdftex/pdflatex.fmtkpathsea库在搜索文件时会按照“用户树优先、本地树次之、发行树兜底”的顺序去找。所以一旦报“找不到”表面上只可能有一个答案这些路径下都没有这个文件或者有但不可读。但背后的原因其实可以拆成好几类。1.2 三类最常见的丢失原因我这些年处理过的案例里pdflatex.fmt消失或不可用基本能归为三类。第一类是根本没生成过。安装TeX Live时中途断网、磁盘空间不足或者包管理器安装的组件不完整导致安装脚本从来没有执行到fmtutil生成格式文件那一步。这种情况很典型尤其是很多人用包管理器安装TeX Live的子集包装的时候没注意依赖关系装完之后既没有pdflatex命令更没有对应的fmt文件。第二类是路径指向了别的地方。机器上不止一套TeX比如系统通过包管理器装的旧版TeX Live和后来手动安装的2020新版本同时存在。PATH环境变量里哪个排前面pdflatex就指向哪一套。如果你执行pdflatex时实际调到的是旧版那套已损坏的目录报错自然就是找不到2020版的fmt文件。这种情况最迷惑因为系统里明明该有的文件都有但你就是调不到。第三类是文件损坏或没有权限读。服务器上多个用户共用一套TeX Live某个用户用fmtutil重建格式文件时以普通用户身份执行失败后留下残缺文件或者root安装后权限配置不对普通用户没有读权限。这三种情况需要用完全不同的思路处理下面分章节展开。2. 高概率原因环境变量把命令引到了别处2.1 先确认当前用的是哪家的pdflatex不要在发现错误后就急着重装整套TeX Live那是最浪费时间的路径。第一步务必确认pdflatex命令本身来自哪里。在终端依次执行which pdflatex which -a pdflatex pdflatex -versionwhich pdflatex告诉你当前shell会调用哪个位置的二进制。which -a会把PATH里所有能找到的同名命令全部列出来通常能看到一个大惊喜机器里藏着两套甚至三套TeX。最后一条pdflatex -version则确认当前命令属于哪个年份的发行版。正常情况应该是类似/usr/local/texlive/2020/bin/x86_64-linux/pdflatex pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2020)如果你的输出显示命令在/usr/bin/pdflatex或者某个/opt/texlive/2019/bin下面问题基本就定位了PATH里指向的不是Te X Live 2020或者顺序不对。2.2 多版本TeX共存时的典型路径冲突我在某公司服务器上处理过一次类似问题。系统里用包管理器装了老版本的TeX Live用于某些脚本调用后来某开发者又手动安装了2020版。由于系统包管理器的/usr/bin在PATH里排在手动安装的/usr/local/texlive/2020/bin之前终端一敲pdflatex实际执行的其实是旧版。旧版的发行树里要么根本没有pdflatex.fmt要么路径配置早就坏了。结果就出现了幻觉般的现象检查/usr/local/texlive/2020/texmf-var/web2c/pdftex/文件明明在但终端就是报错找不到。解决办法不需要删除旧版只要调整PATH顺序。在~/.bashrc或~/.zshrc里把TeX Live 2020的bin目录加到最前面export PATH/usr/local/texlive/2020/bin/x86_64-linux:$PATH修改后执行source ~/.bashrc重新输入which pdflatex确认指向对了再编译就能过。这里要特别注意修改后新开的终端窗口才会生效已经在运行的旧终端即使执行source个别环境下子进程环境也可能残留旧值。2.3 shell缓存和环境变量未生效的细节还有一些情况是PATH本身没错但shell会缓存命令位置。某些shell启用hash功能后第一次找到pdflatex的位置会被记住即使PATH改了下次执行还是用缓存里的旧值。此时先敲hash -r清空缓存再试一次。Windows上也有类似现象而且更隐蔽。安装TeX Live 2020后安装器会在PATH最前面插入D:\texlive\2020\bin\windows但如果电脑里还装过MikTeX或者其他便携版TeX控制面板里看到的PATH列表顺序不一定反映当前进程的实际顺序。改完环境变量必须完全关闭当前终端再重新打开不是新建标签页。某些顽固情况下还需要注销重登因为Windows资源管理器继承环境变量有自己的缓存机制。macOS上which pdflatex返回的往往是/Library/TeX/texbin/pdflatex这个目录本身是一个符号链接指向实际安装路径。如果链接断了或者指向了不存在的目录也会出现“路径找不到fmt文件”的诡异问题这个放到平台差异章节细说。3. 高概率原因之二格式文件压根没生成3.1 安装中断和依赖缺失的识别如果PATH检查完毕确认当前调用的就是TeX Live 2020的pdflatex那问题大概率出在格式文件本身。很多初学者用发行版包管理器安装TeX比如Ubuntu下敲sudo apt install texlive-latex-base装完以后编译简单的文档没问题但一用到某个宏包就报各种缺失再后来甚至直接报找不到pdflatex.fmt。原因是texlive-latex-base只是最基础的一个子集并不包含完整的LaTeX格式构建依赖。部分环境里包管理器会把texlive-latex-recommended、texlive-fonts-recommended等拆成独立软件包缺失任何一个安装脚本都不会触发完整的格式文件生成流程。Linux系统里可以用一个命令快速检查kpsewhich pdflatex.fmt如果没有任何输出说明kpathsea根本没找到文件。这时候再查看发行树下的web2c目录ls -l /usr/local/texlive/2020/texmf-var/web2c/pdftex/正常情况下能看到pdflatex.fmt等一堆fmt文件。如果这个目录是空的或者压根不存在那基本就是安装生成的步骤没跑完。3.2 用fmtutil重建格式文件的标准流程TeX Live本身提供了重建格式文件的标准工具fmtutil。在2020版本里系统级重建用fmtutil-sys用户级重建用fmtutil-user不带后缀的fmtutil会根据当前身份自动选择。最简单的做法是只重建pdflatex这一个格式sudo fmtutil-sys --byfmt pdflatex输出正常时最后会有一行fmtutil: fmtutil-sys: /usr/local/texlive/2020/texmf-var/web2c/pdftex/pdflatex.fmt installed.如果不想一个个试直接重建所有格式文件sudo fmtutil-sys --all这个命令会花几分钟时间但能一次性解决xelatex、lualatex、pdflatex等所有引擎的格式文件缺失问题。这是一个逻辑自洽的选择与其猜哪个坏了不如把整个格式文件集重建一遍。Windows环境可以打开“TeX Live 2020”菜单里的“TeX Live Manager”在设置里勾选“重新生成格式文件”或者在管理员命令行执行相同命令。注意Windows下执行fmtutil-sys前必须确认终端是以管理员身份运行的否则写发行树时会被UAC拦下来。3.3 重建失败时怎么看日志有时代理fmtutil-sys --byfmt pdflatex会失败报错信息一闪而过。这时候不要慌fmtutil会把详细日志写到当前目录的fmtutil.log也经常落在texmf-var/web2c下面。日志里常见的失败原因有某个字体文件缺失、某个宏包语法错误、磁盘空间不足。比较典型的错误行类似Cant locate TFM files for cmr10出现这种情况通常意味着字体映射文件或TFM文件路径配置有问题单纯重建fmt文件解决不了可能需要重新运行sudo mktexlsr sudo -H updmap-sysmktexlsr负责刷新文件名数据库让kpathsea能快速搜索到每个文件。很多“find不了”的诡异问题其实只是文件名数据库没有刷新。顺序上先mktexlsr再updmap-sys再fmtutil-sys --all几乎可以覆盖发行树层面的绝大多数故障。4. 容易被忽视的权限与缓存暗坑4.1 服务器场景下的写权限问题这一类问题在单机用户那里很难遇到但在服务器、实验室共用机器上高发。某高校工作站装了TeX Live 2020管理员用root安装成功后普通用户登录编译时报找不到pdflatex.fmt。检查发行树下的文件权限大概率会发现texmf-var目录里的fmt文件权限是600只有root可读。普通用户执行pdflatex时kpathsea库在搜索阶段就可能把权限问题当成“文件不存在”处理。解法不是给每个用户chmod而是让当前用户用fmtutil-user生成用户自己的格式文件fmtutil-user --byfmt pdflatex这条命令会在用户目录~/.texlive2020/texmf-var/web2c/pdftex/生成属于该用户的fmt文件kpathsea搜索时用户树优先就能绕开系统树权限不足的问题。4.2 用户目录残留的陈旧fmt文件另一个和用户目录相关的坑是很久以前机器上装过另一版TeX~/.texlive2020/texmf-var下残留了损坏的fmt文件。按前面说的搜索优先级用户目录下的文件会优先于发行树的对应文件。如果残留的fmt文件是半成品kpathsea会优先选中这个坏文件然后继续报错。这种问题很有迷惑性因为kpsewhich pdflatex.fmt明明能返回路径但编译就是起不来。处理方式也比较直接删掉用户目录下对应的缓存文件让它回落到发行树。rm -rf ~/.texlive2020/texmf-var/web2c/pdftex/pdflatex.fmt删掉后重新编译如果发行树里的文件完好问题当场解决。如果发行树也没有再执行fmtutil-sys --byfmt pdflatex或者fmtutil-user --byfmt pdflatex重新生成。这种“删掉坏文件再重建”的思路几乎可以处理所有格式文件损坏类故障比在IDE里来回折腾日志高效得多。4.3 TEXMFHOME指向错误的连锁反应还有一种相对少见但确实存在的情况用户在配置文件里手工设置了TEXMFHOME环境变量指向了一个不存在或者权限异常的目录。TeX系统在启动时会认为那个目录也是合法的用户树然后去里面寻找fmt文件。如果那个目录半路出问题kpathsea的搜索步序被打乱就可能报出找不到格式文件的错误。检查方式kpsewhich --var-value TEXMFHOME正常情况下会输出一个用户目录下的路径。如果输出的是一个奇怪的、不存在的路径检查~/.bashrc、~/.profile、还有texmf.cnf里是否设置了TEXMFHOME。大多数用户并不需要手工设置这个变量直接注释掉最省事。5. 三大平台差异速查与一次完整排错回放5.1 Linux发行版特有的坑Linux环境里安装来源决定了后续维护方式。使用apt、dnf这类包管理器安装的texlive目录布局通常遵循FHS规范命令在/usr/bin文件分散在/usr/share/texlive各处更新由包管理器统一管理。而使用官方install-tl脚本安装的TeX Live 2020则集中在/usr/local/texlive/2020自成一派。这两个来源可以共存但不必共存。包管理器在系统升级时可能覆盖配置文件或者触发texlive包的post-install脚本重建格式文件。如果此时官方安装的TeX Live也在使用两边同时跑fmtutil就会发生竞态最终留下残缺的fmt文件。我的建议是同一台机器上选定一个安装来源另一个要么彻底卸载要么在PATH层面完全隔离。Ubuntu/Debian系还要注意一个小的版本陷阱apt install texlive装出来的版本年份可能比2020晚也可能比2020早而texlive-latex-base单独安装的依赖集不一定包含所有格式文件的必备字体。常见画面是报错提示pdflatex.fmt找不到检查后发现/usr/share/texlive/texmf-dist/web2c目录存在但里面没有pdflatex目录。解决方式是补充安装完整组件sudo apt install texlive-latex-recommended texlive-fonts-recommended texlive-plain-generic装完再跑一次fmtutil-sys --all。5.2 Windows下的路径顺序与杀软干扰Windows上最常见的两个变量是PATH顺序和杀毒软件误隔离。PATH顺序前面已经提过。杀软干扰这个问题在TeX Live 2020上尤其值得注意实时防护会把新生成的、签名不明确的.fmt文件当作可疑文件放进隔离区导致编译时读取失败报错就是找不到格式文件。如果是主动防护造成的隔离去杀软隔离区把pdflatex.fmt恢复即可。如果三天两头被隔离可以给texmf-var目录添加白名单或者在安装TeX Live时把安装目录加入排除列表。Windows下检查格式文件是否存在不要用ls用PowerShellGet-ChildItem D:\texlive\2020\texmf-var\web2c\pdftex\pdflatex.fmt另外Win10/11的终端默认可能没有把管理员命令行的工作目录切到texlive\2020下执行fmtutil-sys这类命令时相对路径的日志可能会写到意想不到的目录。建议先cd C:\texlive\2020再操作。5.3 macOS的符号链接失效问题macOS上TeX Live 2020安装完成后/Library/TeX/texbin是一个指向实际二进制目录的符号链接。实际安装路径通常是/usr/local/texlive/2020/bin/universal-darwin或者针对Apple Silicon的arm-darwin。系统更新、迁移助理、或者清理工具误删都可能导致符号链接失效。检查方法ls -l /Library/TeX/texbin readlink /Library/TeX/texbin如果链接指向的目录不存在重新建立sudo ln -s /usr/local/texlive/2020/bin/universal-darwin /Library/TeX/texbin如果你的CPU架构和bin目录不匹配也会出现命令找不到的情况。判断标准很简单/usr/local/texlive/2020/bin/下有哪些架构目录根据uname -m的结果选对应的那一个。macOS上还有个衍生问题从旧版本比如2019版升级到2020版时/Library/TeX/texbin指向新版本但旧版本残留在/usr/local/texlive/2019。PATH里如果加入了旧版路径同样会出现命令与格式文件版本不匹配的情况。处理方式依然是先which pdflatex认准版本再排查。5.4 一次完整排错链路某开发者的重现过程为了把前面的排查逻辑串起来描述一次完整的处理过程。某开发者在某天突然无法编译任何LaTeX文档终端报错I cant find the format file pdflatex.fmt!。他的机器是Windows 10之前一直正常。我给的排查链路是第一步PowerShell里执行Get-Command pdflatex确认命令来自D:\texlive\2020\bin\windows\pdflatex.exe。第二步检查格式文件是否存在路径为D:\texlive\2020\texmf-var\web2c\pdftex\pdflatex.fmt。发现文件不在。到这里问题已经明确为“格式文件确实丢了”而不是环境变量指向问题。第三步打开杀软隔离区发现pdflatex.fmt在隔离列表里。恢复文件后编译恢复正常。这个案例说明了一个观点大多数用户遇到这个报错并不需要真正理解kpathsea的全部机制但需要一套高效的排查顺序。先查命令来源再查文件是否存在然后查文件是否被隔离或权限受限最后才走重建流程。6. 修好之后一次排查清单和一点预防心得针对TeX Live 2020的这个经典报错整个排查链条其实很固定我把每一步浓缩成一张清单方便以后排错时对照。排查步骤执行动作预期结果确认命令来源which pdflatex指向TeX Live 2020的bin目录确认版本一致pdflatex -version显示TeX Live 2020查找fmt文件kpsewhich pdflatex.fmt输出一个存在的路径检查文件权限ls -l对应文件其他用户有读权限尝试重建sudo fmtutil-sys --byfmt pdflatex提示fmt文件已安装刷新数据库sudo mktexlsr无报错检查隔离区杀软隔离区无相关文件被隔离个人习惯是在问题解决后顺手把如下几个小命令写成一个shell函数下次再出类似问题一条命令就能把所有诊断信息全部拉出来。Linux或macOS下可以直接放在~/.bashrc里texdiag() { echo which ; which pdflatex echo version ; pdflatex -version | head -1 echo fmt path ; kpsewhich pdflatex.fmt echo ls ; ls -l $(kpsewhich pdflatex.fmt) 2/dev/null echo home ; kpsewhich --var-value TEXMFHOME }跑一次texdiag绝大多数“找不到fmt文件”的原因都能直接看出来。如果你在排查过程中发现命令指向了奇怪的目录先改PATH如果文件根本不存在先重建再考虑其他如果文件权限不对优先用fmtutil-user生成用户级文件如果一切正常但编译还是挂那就去杀软隔离区和~/.texlive2020缓存目录里找找真相。最后再分享一点实际体会TeX Live这套系统最让人头疼的往往不是排错本身而是“以为自己在排错实际在瞎猜”。很多人一看到这种报错就卸载重装装完还是同样问题白白浪费几个小时。实际上只要抓住which和kpsewhich这两条命令先搞清楚“命令在哪”“文件在哪”九成以上的问题都能在三分钟内定位。剩下的就是按本章顺序挨个试一遍基本不会再有意外。
阅读完成 · 觉得有帮助?
咨询建站