用 Ubuntu 写 LaTeX 的人,十有八九都会遇到同一个尴尬:系统里明明装了 texlive,编译论文时却提示某个宏包不存在,或者宏包版本太老,跟新模板对不上。这时候tlmgr就是救命的东西。它是 TeX Live 自带的包管理器,全称 TeX Live Manager,专门负责在线安装、更新、删除宏包,也能管理整个 TeX Live 的版本升级。这篇就围绕“Ubuntu 下用命令行操作 tlmgr 在线更新 packages”展开,把我实际用下来的命令、参数、坑和排查思路都讲清楚,适合刚接触 TeX Live 的新手,也能给折腾了一阵子还理不清头绪的人做个参考。
## 1. 为什么要用 tlmgr:TeX Live 的包管理与更新逻辑 ### 1.1 apt 里的 texlive 与官方 texlive 其实是两回事 很多 Ubuntu 用户的第一套 TeX 环境是 `sudo apt install texlive-full` 装出来的。这套方案简单,但有一个绕不开的问题:Ubuntu 的软件源更新节奏比较慢,仓库里的 TeX Live 版本往往落后官方一年甚至更久。宏包更新更是基本靠等,今天 CTAN 上某个宏包已经修了 bug,apt 源里还停留在半年前的版本。 更麻烦的是,apt 安装的 texlive 虽然也附带 tlmgr,但它的 `tlmgr` 是被“裁剪”过的,默认仓库指向的是一个本地目录而非在线源,运行时会提示 `cannot find remote repository` 之类的错误。不是说完全不能用,但要想真正发挥 tlmgr 在线更新的能力,建议还是从官网用 `install-tl` 脚本装官方版本,装完以后 tlmgr 才是一个完整可用的工具。 我自己的选择是:把 apt 里的 texlive 彻底卸掉,改用官方安装脚本装到 `/usr/local/texlive` 下面。这样 TeX Live 完全独立于系统包管理器,更新、回滚都能自己控制,不会再被 apt 的依赖关系牵扯。 | 对比项 | apt 安装的 texlive | 官方 install-tl 安装 | | --- | --- | --- | | 更新频率 | 跟随 Ubuntu 源 | 跟随 CTAN 每日/月度更新 | | tlmgr 可用性 | 功能受限,可能无法在线更新 | 完整可用 | | 宏包版本 | 一般偏旧 | 更新及时 | | 与系统包管理器的关系 | 耦合,受依赖影响 | 独立,互不干扰 | | 适合人群 | 只写简单文档、不追新 | 论文排版、需要最新宏包 | 如果你还没装官方版本,也不要急着删 apt 的,可以先在用户目录下跑一份,两边共存,等确认没问题再清理。后面讲到的所有命令,我默认你用的是官方 install-tl 安装的 TeX Live。 ### 1.2 tlmgr 的工作机制与 packages 组织方式 tlmgr 的本质是一个 Perl 脚本,它通过读取 TeX Live 的包数据库(texlive.tlpdb)来管理所有宏包、字体、格式文件、文档和源码。这个数据库记录了每个 package 的版本、依赖关系和文件清单,更新时 tlmgr 先拿到远端仓库的包数据库,然后跟本地比对,找出需要增删改的项。 在 TeX Live 的世界里,“package”不完全等同于你 LaTeX 文档里 `\usepackage` 的那个名字。比如你写 `\usepackage{beamer}`,实际对应的 TeX Live 包可能是 `beamer`,但一个宏包可能还依赖 `pgf`、`xcolor`、`translation-zh-cn` 等一堆底层包。tlmgr 在安装和更新时会自动处理这些依赖,这一点比手动从 CTAN 下载 `.sty` 文件扔进目录要省心得多。 另一个需要理解的概念是,TeX Live 每年发布一个大版本(2023、2024、2025 等),版本之间宏包差异很大。tlmgr 默认只更新当前版本范围内的宏包,不会跨版本升级 texlive 本身。跨版本升级是 `tlmgr update --self` 之后通过重新运行 `install-tl` 或者 `tlmgr --repository` 指定新版仓库来实现的,普通宏包更新不需要担心系统被升到不兼容状态。 ### 1.3 安装环境准备:从 install-tl 到 PATH 配置 要在 Ubuntu 下让 tlmgr 正常工作,正确设置 PATH 是最容易被忽略的第一步。官方 install-tl 脚本安装完以后,二进制文件在 `/usr/local/texlive/2025/bin/x86_64-linux`,但系统默认不会自动加入 PATH,你直接在终端敲 `tlmgr` 会提示命令不存在。 我通常在 `~/.bashrc` 或 `~/.zshrc` 里加上这么几行: ```bash export PATH=/usr/local/texlive/2025/bin/x86_64-linux:$PATH export MANPATH=/usr/local/texlive/2025/texmf-dist/doc/man:$MANPATH export INFOPATH=/usr/local/texlive/2025/texmf-dist/doc/info:$INFOPATH注意路径里的2025要换成你实际安装的版本号。环境变量加完以后执行source ~/.bashrc,再敲tlmgr --version验证。这一步如果没做好,后面所有操作都会卡在“命令找不到”上,但它本身又特别简单,所以有必要单独提醒一下。
2. tlmgr 常用命令拆解:从查询到更新一整套操作
2.1 命令总览与核心操作映射
我把日常使用频率最高的 tlmgr 命令整理成了一张表,方便查询,后面再针对几个重点做详细说明:
| 命令 | 作用 |
|---|---|
tlmgr update --self | 更新 tlmgr 自身 |
tlmgr update --all | 更新所有宏包 |
tlmgr update <pkg> | 更新指定宏包 |
tlmgr update --dry-run --all | 预演更新,只显示计划不实际执行 |
tlmgr install <pkg> | 安装新宏包 |
tlmgr remove <pkg> | 删除宏包 |
tlmgr info <pkg> | 查看宏包信息 |
tlmgr search <keyword> | 搜索包含关键字的宏包 |
tlmgr list --only-installed | 列出本地已安装宏包 |
tlmgr option repository <url> | 设置/查看宏包仓库地址 |
tlmgr backup | 备份宏包相关配置 |
tlmgr dump-tlpdb | 导出包数据库 |
日常更新流程我习惯先用--dry-run看一下有多少包要更新、更新内容是什么,避免一上来就--all把系统改得面目全非。
2.2 关键参数解析:--self、--all、--dry-run、--no-auto-remove 等
tlmgr update --self这条命令非常重要,甚至应该放在其他所有更新之前。tlmgr 本身也是 TeX Live 的一个包,它的版本如果太老,可能无法正确解析新版仓库的数据库格式。我遇到过的情况是:老版本 tlmgr 访问新仓库时直接报Unknown directive或TLPDB::from_file failed,先跑一次--self就解决了。
--all表示更新所有可更新的宏包,但它有几个配套参数很有用:
--no-auto-remove:默认情况下 tlmgr 更新时会自动删除不再被依赖的包,加了这个参数就不会删。--no-auto-install:依赖缺失时默认会自动安装新依赖包,加了这个参数就只更新不新增。--force:强制重新下载并安装,即使版本号没变化。
--dry-run则相当于预演模式,它会把将要执行的更新列表、涉及的依赖、可能的冲突全部打印出来,但不会改动系统。这个参数尤其适合先确认更新范围。
举个例子,一条相对保守的更新命令是:
tlmgr update --self && tlmgr update --dry-run --all先升级自身,再预览全部更新计划。预览没问题以后,再执行正式的tlmgr update --all。
2.3 仓库(repository)切换与加速
tlmgr 默认从 CTAN 主站下载,网络条件不好时会很慢,甚至经常断。解决办法是把仓库切换到国内镜像,设置方法很简单:
tlmgr option repository https://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/tlnet也可以使用中科大镜像、腾讯镜像等,地址格式基本相同。设置完以后,用下面的命令验证:
tlmgr option repository它会打印当前使用的仓库地址。除了永久切换,也可以临时指定仓库而不修改配置:
tlmgr update --all --repository https://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/tlnet这种方式适合只想临时加速一次的情况。注意,不同的 TeX Live 大版本要对应不同路径的 tlnet 目录,比如 TeX Live 2025 用.../tlnet,2024 用.../2024/tlnet这种带年份的路径,具体看镜像站目录结构。搞错版本会导致版本不匹配的报错。
3. 实战:Ubuntu 下用 tlmgr 在线更新 packages 的完整流程
3.1 前期检查:版本、PATH、仓库状态
正式更新前,我习惯做三步检查,步骤虽简单但能省掉后面一堆麻烦。
第一步,确认 tlmgr 命令可用:
which tlmgr正常情况下会输出类似/usr/local/texlive/2025/bin/x86_64-linux/tlmgr的路径。如果输出为空,说明 PATH 没设置对,回到 1.3 节检查环境变量。
第二步,确认 TeX Live 版本与仓库是否匹配:
tlmgr --version tlmgr option repository--version显示当前版本号,option repository显示仓库地址。如果仓库路径里的年份跟版本号对不上,后续更新会报错。
第三步,确认 sudo 权限和当前用户。tlmgr 的安装模式分两种:如果你用普通用户身份安装 TeX Live,它默认装在用户目录里,更新不需要 root 权限;如果用 install-tl 时的-root方式装到系统目录,更新时就需要 sudo。后面专门有一节讲 sudo 的坑,前置检查阶段只要心里有数就好。
3.2 第一次更新:从 tlmgr update --self 到 update --all
刚装好 TeX Live 或者隔了很久才想起更新时,我建议按这个顺序操作:
tlmgr update --self这一步会把 tlmgr 自身升级到与仓库匹配的版本。老版本 tlmgr 更新到新版本时,可能还要补装一些 Perl 模块,它会自动下载依赖,网络慢的话稍等一会儿。
然后执行预演:
tlmgr update --dry-run --all输出会列出一长串待更新包,包括包名、旧版本、新版本。扫描一眼有没有特殊标记的包(比如(forced)、(removed)),确认没有明显异常后,再真正更新:
tlmgr update --all首次全量更新的下载量可能达到几百 MB,耗时取决于网速。更新过程中终端会不断打印包名和版本号,最后显示Total或done或类似提示,表示完成。
如果中途断网或者 Ctrl+C 中断了,再次执行同样的命令即可,tlmgr 会跳过已经更新到最新版本的包,只补剩余部分。
3.3 按需更新:只更新某个具体宏包
全量更新固然省心,但有时候你只是编译某个文档时缺一个宏包,或者某个宏包爆出 bug 急需修复,这时按需更新更快也更安全。
先搜索包名:
tlmgr search beamer搜索结果可能很多,可以用更精确的方式过滤:
tlmgr info beamer确认包名无误后安装或更新:
tlmgr install beamer tlmgr update beamer更新指定包时,tlmgr 会把该包依赖的其他包也一起检查,如果有依赖更新,它默认也会更新这些依赖。这个行为是合理的,否则新版本宏包可能依赖新版本的底层库,只更新一个包反而容易出问题。
另外,如果你怀疑某个宏包和模板不兼容,可以回退到上一版本。TeX Live 的 tlmgr 支持安装指定版本的包,但前提是仓库里保留了历史版本。多数在线仓库只保留当前版本,所以回退操作通常依赖于在更新前用tlmgr backup做了本地备份,不然回退会很麻烦。
3.4 权限管理:sudo 的正确姿势与坑
在 Ubuntu 上用 tlmgr 更新系统级 TeX Live 时,最常见的问题是明明加了sudo却报错命令找不到,或者更新到一半提示权限错误。
原因很简单:sudo默认不会继承普通用户的 PATH。你在用户环境里设置了/usr/local/texlive/2025/bin/x86_64-linux,但 sudo 使用的 secure_path 是系统默认值,不包含这个路径。所以sudo tlmgr会提示sudo: tlmgr: command not found。
解决办法有三个:
一是执行时写全路径:
sudo /usr/local/texlive/2025/bin/x86_64-linux/tlmgr update --all二是调用env把 PATH 带过去:
sudo env PATH="$PATH" tlmgr update --all三是直接切换到 root 用户再执行:
sudo -i tlmgr update --all我个人的习惯是第一种,简单直接,也避免权限环境的干扰。
另一个权限问题是:如果安装时用的普通用户加sudo方式,HOME 目录可能影响 tlmgr 读取用户配置。tlmgr 在执行时会尝试读取~/texmf等用户目录,如果这些目录的属主是普通用户,sudo 后变成 root,反而引发写入冲突。所以我的建议是:要么完全用普通用户身份管理用户级 TeX Live,要么完全用 sudo 管理系统级 TeX Live,不要混着来。
4. 更新后的收尾工作与细节技巧
4.1 刷新文件名数据库与字体缓存
很多人在tlmgr update --all之后就以为万事大吉,直接去编译文档,结果报错说找不到某文件。这通常是因为 TeX 软件包更新后,文件名数据库还没有刷新。
LaTeX 在编译时会通过kpsewhich查找文件,而这个查找机制依赖一个叫ls-R的文件名数据库。宏包更新后,新文件不会自动进入数据库,需要手动刷新。如果更新是在系统级目录,执行:
sudo mktexlsr如果是在用户级目录,执行:
mktexlsr字体相关宏包更新后,还要刷新字体映射,否则 PDF 里的字体可能错乱或缺失:
sudo updmap-sys宏包更新还可能影响 TeX 的 format 文件(比如 LaTeX 内核、ConTeXt 格式),这些文件也需要重建,一般 tlmgr 会自动触发fmtutil-sys的重建,但如果发现编译时 format 相关报错,可以手动执行:
sudo fmtutil-sys --all这三条命令是 TeX Live 更新后的“三级刷新”,记下来能少踩很多坑。
4.2 利用 TEXMFHOME 实现用户级宏包隔离
我强烈建议普通用户建立一个自己的~/texmf目录(即 TEXMFHOME),把不属于 TeX Live 仓库的宏包放在里面,然后用tlmgr只管仓库内包的更新。
原因是,有些宏包是私人定制或者公司内部 Tools,它们不在 CTAN 上,tlmgr 永远不会管它们。如果你把它们混在仓库目录里,更新时要么被覆盖,要么永远不更新导致混乱。放在 TEXMFHOME 下,你的\usepackage照样能找到这些文件,仓库更新又不会误伤它们,两边相安无事。
查看当前 TEXMFHOME 位置:
kpsewhich -var-value TEXMFHOME默认情况下就是~/texmf,把自定义宏包按tex/latex/<包名>/<文件名>的目录结构放进去,再执行mktexlsr即可被 LaTeX 找到。
4.3 大版本升级前的备份与回滚方案
tlmgr 的更新正常情况下不会导致灾难性故障,但意外总有可能。每次大规模更新前,我建议至少对包数据库做一次备份:
tlmgr dump-tlpdb > tlpdb-$(date +%Y%m%d).txt这个文件包含了当前所有已安装宏包的版本和文件列表,万一需要定位问题,可以用它来对比。
真正要回滚宏包到旧版本时,更实用的做法是启用 tlmgr 的自动备份功能:
tlmgr option autobackup 1启用后,每次更新宏包前,tlmgr 会把旧版本备份到备份目录,之后可以用:
tlmgr restore <包名>来恢复指定宏包的上一版本。这个功能默认关闭,因为备份会占用磁盘空间,但考虑到论文提交前宏包更新导致的编译失败问题,我觉得开着踏实得多。
5. 常见问题与排查:更新 packages 时最容易踩的坑
| 错误现象 | 根本原因 | 解决办法 |
|---|---|---|
tlmgr: command not found | PATH 未配置或 sudo 环境不含 PATH | 见 3.4,写全路径或设置 PATH |
TLPDB::from_file failed | tlmgr 版本过老,仓库不匹配 | 先tlmgr update --self或指定正确仓库 |
cannot find remote repository | 仓库未设置或指向本地目录 | tlmgr option repository <url> |
| 下载慢/超时 | 网络问题 | 切换国内镜像源 |
checksum mismatch | 下载文件损坏或镜像不同步 | 重试或换镜像源 |
| 更新后宏包找不到 | 文件名数据库/缓存未刷新 | 跑mktexlsr、updmap-sys、fmtutil-sys |
| 更新后 LaTeX 版本过旧 | TeX Live 大版本未升级 | 跨版本升级需要重新 install-tl |
5.1 LaTeX 内核与宏包版本不匹配
这是更新后最典型的故障:宏包更新到新版,但 LaTeX 内核还是旧的,于是编译时报一堆LaTeX Error: File X not found或奇奇怪怪的选项错误。一般是因为 tlmgr 只更新宏包,没有同步更新 format 文件。
解决的办法是重建 format:
sudo fmtutil-sys --all然后刷新数据库:
sudo mktexlsr如果问题依然存在,检查一下是不是只更新了某个宏包而没有更新它的依赖。这时跑一次全量更新:
tlmgr update --all通常能补上缺失的中间版本。
5.2 用户目录下的 texmf 与仓库包冲突
有一种情况容易让人摸不着头脑:tlmgr 显示某个包已经是最新版,但编译时使用的还是旧宏包文件。真相往往是你~/texmf目录里也有一份同名宏包,而 TEXMFHOME 在查找顺序里排在 TEXMFDIST 之前,于是 LaTeX 优先加载了你的私藏旧版。
排查方法是检查宏包实际来源:
kpsewhich beamer.sty它会输出实际加载文件的完整路径。如果路径指向~/texmf,基本就是自己目录里的旧文件在捣乱,清理掉即可。如果没有清理必要,至少要做到心里有数,别让 tlmgr 更新白跑一遍。
5.3 更新过程被中断后的恢复
全量更新遇到网络波动,或是不小心按了 Ctrl+C,Terminal 会留下一堆半下载的临时文件。这时不要慌,再次执行相同的更新命令,tlmgr 会从断点继续,已完成的包不会再重复下载。
如果提示文件锁占用:
lsof /usr/local/texlive/2025/tlpkg查到占用进程后,kill 掉或等它结束再重试。需要注意的是,不要在 TeX 编译正在进行时执行 tlmgr 更新,两者同时访问文件库可能造成数据库损坏。
5.4 用 tlmgr list 验证更新效果
更新完成以后,验证是否生效也很关键。查看某个包当前版本:
tlmgr info <包名>查看所有可更新包是否已经清零:
tlmgr update --dry-run --all如果输出nothing to update或者不再列出新包,说明已经更新到位。如果还想确认具体某个宏包的安装时间或版本,用tlmgr list --only-installed | grep <包名>过滤查看。
6. 一点个人习惯与经验总结
最后说点自己的使用习惯。我一般只在两类时机用 tlmgr 做全量更新:一是新装好 TeX Live 后立刻把环境和字体同步到最新,二是每个月固定做一次例行更新。平时写文档遇到缺包或宏包报错,都是按需用tlmgr install或tlmgr update <包名>精准处理。这样既不会因为频繁全量更新引入意外,又能保证关键宏包及时修复。
还有一点值得养成习惯,就是每次重要更新前先看一眼仓库源。换了镜像后,tlmgr 更新速度和稳定性都有明显提升,以前下载几百 MB 包要等很久也稳定完成了。如果 y 你刚切换到镜像源,记得先跑一次tlmgr update --self让工具自身完成版本适配,再执行宏包更新,整体流程会顺畅很多。
用 tlmgr 管理 TeX Live packages 属于那种“理解以后就觉得很简单”的事,但坑往往藏在环境变量、仓库地址、权限模式这些不起眼的地方。仔细过一遍上面的步骤,基本能避免九成问题。