如果你做过仿真、数据处理或者科研计算,大概率对MATLAB的网络许可证并不陌生。我身边不少同事第一次遇到License Manager Error -31这个报错时,第一反应都是“许可证是不是过期了”“服务器是不是挂了”,结果重启服务、重新激活全试了一遍,问题依旧。最后排查才发现,客户端和许可证服务器的系统时钟整整差了8个小时,而问题根源就出在“时区不一致”上。这背后其实是一整套 FlexLM 时间校验机制在起作用,远比表面上一个报错码复杂。
这篇文章不只是做报错速查,我会把时间校验原理、时区差异为什么能触发 -31、Windows 和 Linux 下如何修复、以及长期维护时怎么避免再踩坑一起讲清楚。无论你是刚接触 MATLAB 网络许可证的新手,还是已经维护了一段时间、正在为偶发报错头疼的工程师,这篇内容都值得完整看一遍。
1. 手把手排查:时区问题如何触发MATLAB的-31报错
1.1 网络许可证的“签到”逻辑
要理解 -31,先得知道 MATLAB 网络许可证是怎么工作的。MATLAB 授权服务器上运行着一个许可证守护进程,它管理着整套许可证资源。客户端机器上的 MATLAB 启动时,会通过环境变量或者许可证文件里的配置,找到这台服务器,然后申请一个“许可证租约”。
这个过程很像去健身房刷会员卡:你的手环信息(客户端时间戳)和门店系统(许可证服务器)之间必须能对得上。如果手环显示的时间和门店系统差太多,前台就有理由怀疑这张卡有问题,拒绝你入场。FlexLM 的做法类似,客户端向服务器发起许可请求时,会把本机的系统时间一并带过去,服务器把自己的当前时间和客户端时间进行比较。一旦差值超过某个阈值,服务器就认为客户端时钟异常,拒绝签发许可,MATLAB 客户端随即报出License Manager Error -31。
这里的“阈值”通常被描述为 5 分钟,也就是 300 秒。不同版本、不同厂商的 FlexNet 配置可能略有差异,但默认逻辑基本一致:客户端和服务器的时间差必须控制在一个很小范围内,否则授权不可用。
1.2 时区差异到底错在哪
很多人的第一直觉是:时区不同,本地时间显示差好几个小时,报错理所当然。但严格来说,计算机系统时间分两层:一层是硬件级、UTC 基准的绝对时刻,另一层是时区偏移。也就是说,一台机器可以设置为东八区本地时间显示,另一台设置为 UTC 标准时间显示,只要两台机器各自都知道自己的 UTC 基准是多少,它们的“绝对时刻”是可以完全一致的。
理论上,FlexLM 校验的是绝对时刻偏差,而不是你眼睛看到的本地时间差异。单纯“时区显示不同”,但两台主机都正确配置了时区、并且通过 NTP 同步到了同一个 UTC 基准,是不应该报 -31 的。真正坑人的场景往往是这样的:服务器设成了东八区,客户端管理员图省事,手动改了系统时间而没有设置正确的时区;或者两台机器分别用了不同时区,但硬件时钟存放的基准不一致,导致它们各自的 UTC 绝对时刻本身就差了好几个小时。
所以,排查时最忌讳只看date命令输出的本地时间。正确的做法是看date -u,也就是 UTC 时间。如果两台机器date -u输出的差值小于 300 秒,时间校验就能过;如果差值很大,那不管本地时间看起来多“合理”,MATLAB 都会认为你的系统时钟错了。
1.3 官方允许的“5分钟偏差”到底是什么
300 秒的容差,听起来很宽松,但实际运维里非常容易被突破。我遇到过的情况是:某内网环境不能访问外网,没有 NTP 同步,服务器和客户端运行了几个月后,各自主板上的硬件时钟漂移了几分钟,于是一台机器显示 10:02,另一台显示 10:08,MATLAB 直接报 -31。这种情况和时区无关,只是纯粹的时间不同步。
还有一种更隐蔽的情况:客户端的时区设置错了。比如服务器在东八区,客户端在 UTC,但客户端管理员手动把本地时间调成了和服务器一样的本地时间,而不是改时区。这样一来,客户端的 UTC 基准其实变成了“东八区时间”,本地却显示成 UTC,结果就是 UTC 绝对时刻相差了 8 小时。表面看两台机器date显示的时间一样,但date -u立刻露馅。
理解了这一层,后续所有修复动作就会很清晰:不是单纯“把两个时区改成一样”就完事,而是要让两台机器在 UTC 绝对时刻上保持一致。
2. 读懂License错误文本:-31与-95、-13的区别和联系
2.1 -31报错的典型文本和隐藏含义
启动 MATLAB 时,如果许可证校验失败,通常会弹出一个对话框或同时在命令行输出错误码。License Manager Error -31的经典描述长这样:
License Manager Error -31 MATLAB is unable to connect to the License Manager. System clock is set incorrectly. Check that the date, time, and time zone are correct.这段文本最坑人的地方在于,它把“date, time, and time zone”并列在一起。很多人只看到 date 和 time,就跑去把客户端时间手动调成和服务器一致,却忽略了 time zone 也是一个独立变量。如果客户端时区本来就不对,你手动把时间调成服务器显示值,过几天重启之后又会漂移回来,或者因为网络时间协议自动同步,时间又被“纠正”回错误的时区对应的正确绝对时刻,于是再次报 -31。
另一些情况下,文本可能只写“The time difference between the license server and system clock is too large.”,没有提到时区。这时更要警惕:到底是服务器的时钟漂了,还是客户端的时钟漂了,又或者两边的时区都正常,但硬件时钟基准不同。只看报错文本无法回答这些问题,必须看具体时间数据。
2.2 与-95、-13的快速区分
很多时候,网络许可证报错不只有 -31。运维现场经常把 -31、-95、-13 混在一起讨论,但它们的原因完全不同,修复手段也南辕北辙。
| 错误码 | 常见提示 | 核心原因 | 解决方向 |
|---|---|---|---|
| -31 | System clock is set incorrectly | 客户端与服务器时间差超过阈值 | 统一时区、同步时间 |
| -95 | Cannot connect to license server | 网络不通、服务器未启动、端口被防火墙拦截 | 检查网络、lmgrd 进程、端口 |
| -13 | This feature is not available | 许可证功能不可用或未启动 | 检查 feature 名称、许可证文件内容 |
| -39 | Invalid host | 主机名/主机ID与许可证不匹配 | 检查 license.dat 的 HOSTID |
如果你是第一次排查,先从错误码入手。如果是 -95,大概率是网络链路问题,别浪费时间调时区。如果是 -31,再进入时间排查流程。如果同时出现多个错误码,比如先 -95 再 -31,那可能是许可证服务本身异常,连带影响了时间校验流程。
2.3 一个快速判断口诀
我个人总结了一个非常简单的判断方法,适用于绝大多数 -31 现场:在两台机器上分别执行同样的命令,比较输出。
date -u date +%sdate -u显示的是 UTC 时间,date +%s显示的是 Unix 时间戳。只要这两台机器的date +%s输出相差小于 300,时间本身没问题;如果相差很大,那就先不要去动许可证文件,先把时间问题解决。这条经验帮我省下了无数次无效重启。
3. Windows和Linux客户端时钟修复实操
3.1 Windows客户端的时区与时间同步
Windows 客户端是 MATLAB 最常见的运行环境,处理起来也最直接。先打开“设置 -> 时间与语言 -> 日期和时间”,把“自动设置时间”和“自动设置时区”打开。如果公司网络允许访问互联网时间服务器,这一步通常就够了。
但如果你的办公网是内网、不允许出公网,或者系统里时间源被组策略锁死,那就需要用命令行。
查看当前时区:
tzutil /g设置时区,例如东八区,需要管理员权限:
tzutil /s "<你就是东八区对应的时区ID>"这里我不直接写死某个时区 ID,因为不同语言版本的系统,时区 ID 显示方式可能不同。最稳妥的办法是先运行tzutil /l列出全部时区,从列表里找到你需要的东八区项,复制它的 ID 再执行。注意,tzutil改的是时区设置,不会自动把时间同步到这个时区的正确时刻,所以之后还要同步一次时间。
强制同步时间:
net start w32time w32tm /resync实测中,w32tm /resync有时会返回“没有可用时间源”,这时候要确认 Windows Time 服务是否在运行,以及当前时间源配置是否正确。如果内网有 NTP 服务器,可以用下面的命令手动指定:
w32tm /config /manualpeerlist:"你的NTP服务器地址" /syncfromflags:manual /update w32tm /resync改完时区、同步完时间,建议再执行一次date /t和w32tm /stripchart /computer:你的许可证服务器 /samples:1做对比,确认客户端和服务器的时间差已经小于 5 分钟,再启动 MATLAB。
3.2 Linux客户端的时区与时间同步
Linux 下的 MATLAB 客户端同样会遇到 -31,而且命令更集中。现代 Linux 系统一般使用 systemd,一条命令就能看到所有时间状态:
timedatectl输出里会明确显示本地时间、UTC 时间、时区 ID,以及 NTP 是否启用。这是排查时最好的起点。
修改时区,同样用占位符代替具体时区 ID,避免不同发行版和不同语言环境的差异:
sudo timedatectl set-timezone "<你的时区ID>"之后确认系统时间和日期是同步的:
sudo timedatectl set-ntp true如果使用的是 chrony 作为 NTP 客户端,还可以手动快速同步一步到位:
sudo chronyc makestep对于没有 systemd 的旧系统,可以使用传统命令,先把硬件时钟设为 UTC:
sudo ln -sf /usr/share/zoneinfo/<你的时区ID> /etc/localtime sudo hwclock --systohc --utc然后安装并使用 ntpdate 手动同步:
sudo ntpdate <你的NTP服务器地址>需要注意的是,部分云服务器默认没有安装 ntpdate,而且系统里可能同时存在 chrony 和 systemd-timesyncd,多个时间同步服务会互相抢时间源。排查时如果发现时间一直在跳,先看是不是有两个 NTP 服务同时在工作。
3.3 虚拟机和容器的额外坑
我在容器环境里踩过的坑,比物理机多得多。Docker 容器默认是 UTC 时区,而宿主机往往是东八区。如果 MATLAB 跑在容器里,而许可证服务器跑在宿主机上,两边date -u其实是一致的,因为容器共享宿主机的内核时钟,通常不会触发 -31。但如果你在容器里运行date,看到的时间和宿主机差 8 小时,很多人就会手贱去容器里手动改时间,结果反而把容器内的时钟偏差改乱了。
更稳的容器做法是:不要在容器启动后手动改时间,而是把宿主机的时区文件挂载进去,或者调整环境变量TZ。如果是定制镜像,预先安装 tzdata 并设置时区就可以了。虚拟机也有类似问题,尤其是从模板克隆出来的虚拟机,如果模板时钟本身就不准,克隆后所有节点的系统时间会一起偏移,这时候光改时区没用,必须对每个节点单独做时间同步。
4. 许可证服务器端检查与长期时间治理
4.1 lmstat与lmdiag快速体检
修复客户端之前,先确认许可证服务器自己是否正常。FlexLM 自带了一套诊断命令,其中最常用的是lmstat。在服务器上执行:
lmstat -a -c license.dat输出里能看到lmgrd是否在运行、各功能(feature)的状态、当前有多少用户在占用等。如果lmstat本身都连不上服务器,那就不是时间问题,而是服务没起来。
进一步诊断具体功能,可以用:
lmdiag -c license.dat -l matlab这段命令会尝试真实地去服务器申请一个许可证,如果时间校验失败,它会报出具体错误原因,比盲目重启服务有效得多。我在实际运维里,遇到过好几次服务器端时间漂移,但lmstat显示一切正常,只有跑lmdiag才发现是时间问题。所以每次排查 -31,我都会把lmdiag作为第二步,而不是直接去改客户端。
4.2 调整FlexLM时间容忍度的进阶选项
有些运维工程师问我,能不能把 FlexLM 的时钟容忍度调大一点,比如从默认 5 分钟改成 1 小时,这样时间漂移就不容易报错了。理论上 FlexLM 配置文件里确实有和时钟超时相关的参数,可以通过lmf.conf之类的文件去设置。但这里我必须提醒一句:不同 FlexNet 版本的参数名差异很大,而且厂商未必支持这个调整,生产环境贸然修改,很可能导致其他更隐蔽的授权问题。
我的建议是,把调大容差当成一个“应急实验”,而不是长期方案。真正该做的,是把时间同步做好。时间同步做到位之后,容差 5 分钟还是 1 小时根本不重要,因为你永远不会触发它。
4.3 长期方案:统一NTP时间基线
排查解决一次 -31 很容易,难的是以后不再犯。长期方案只有一个核心:让所有涉及许可证校验的主机,都使用同一个 NTP 时间基线。
具体落地可以分三步。第一步,在内网搭一台内部 NTP 服务器,让它同步上游时间源,再向下分发。如果内网完全隔离,就指定某几台稳定机器作为基准,其他节点向它们同步。第二步,在这台 NTP 服务器上,同时给许可证服务器和所有 MATLAB 客户端配置自动同步。Windows 用w32tm,Linux 用 chrony 或 systemd-timesyncd。第三步,写一个巡检脚本,定期比较各节点date +%s与基准节点的差值,超过 60 秒就告警,把问题消灭在用户报错之前。
时区本身怎么设置,反而可以按业务习惯来。服务器用统一的 UTC 便于日志对比,客户端用东八区方便本地用户查看,都没有问题。关键不是大家显示的时间字符串一样,而是 UTC 绝对时刻一致。
5. 避坑经验:故障排查路线图与常见问答
5.1 一套可以抄作业的排查路线
以下是我自己整理的一套排查路线,适合每次遇到 -31 时按顺序执行,避免东一榔头西一棒子。
- 先记录完整报错文本,确认确实是 -31,而不是 -95 或 -13。
- 在客户端和许可证服务器分别执行
date -u和date +%s,拿到两个时间戳。 - 计算两个时间戳的差值。如果大于 300 秒,进入第 4 步;如果小于 300 秒,进入第 5 步。
- 检查两端时区设置。Windows 用
tzutil /g,Linux 用timedatectl。把出错端的时区改为正确的东八区或 UTC,然后重新同步时间,再回到第 3 步确认。 - 如果时间差已经小于 300 秒但仍然报 -31,检查系统里是否有多个时间同步服务冲突,或者检查许可证服务器上是否有可疑的 VENDOR daemon 异常。此时用
lmdiag -c license.dat -l matlab做一次真实诊断。 - 确认许可证服务正常后,重启 MATLAB 客户端。不要只重启客户端,而忽略服务器端。如果服务器端异常,
lmstat -a里通常能看到线索。
这套路线我用了很久,百分之九十的 -31 都能在 20 分钟内定位。
5.2 常见误区
先列几个我见过最多的错误认知,都是真实踩坑案例。
第一个误区是“把客户端时间手动调成和服务器一样就完事”。这个操作只骗过了人眼,没有骗过 FlexLM。因为系统时间是一个绝对概念,手动调完不校验时区,过一晚就又会因为各种自动同步而跳回去。
第二个误区是“两台机器时区改成一样就安全了”。时区一致只是第一步,如果两台机器都没有 NTP 同步,硬件时钟漂移照样会让它们越过 300 秒的容差线。时区一致不等于时间同步。
第三个误区是“只有客户端时间有问题”。服务器时间漂移的案例在真实环境里很常见,尤其是长期不关机的物理服务器。排查时不要只盯着客户端,两边都要看。
第四个误区是“改完时间后不用重启 MATLAB”。MATLAB 启动时才去申请许可证,启动过程中读取的时钟状态会被缓存,旧的错误会话可能一直保留到 GUI 关闭。改完时间后,最好完整退出启动中的 MATLAB 进程,再重新打开。
5.3 问题速查表
我把现场最常见的几个场景整理成一张速查表,仅供参考和快速定位。
| 现象 | 可能原因 | 处理方向 |
|---|---|---|
| 本地时间显示只差几分钟但报 -31 | 时区错误导致 UTC 偏移,或 NTP 未同步前的漂移 | 查看date -u,修正时区,重新同步 |
| 时区相同依然报 -31 | 两端未同步,硬件时钟漂移 | 配置 NTP,重启许可证服务后重试 |
| 同一集群中部分节点报错,部分正常 | 被报错节点的 VM/容器时钟漂移,或模板克隆文件残留 | 对单个故障节点单独同步并检查 NTP 服务 |
| 改用本地许可证后正常,用网络许可证报 -31 | 本地许可不校验时间,网络许可校验 | 回到了时区与同步排查主流程 |
| 报 -31 但同时伴随 -95 | 许可证服务本身异常,或网络端口问题 | 先解决服务和网络,再处理时间 |
5.4 几个运维上的小建议
最后说几点个人经验,不涉及具体配置,但对长期维护很有帮助。
第一,别只看报错码。MATLAB 的许可证错误码是高度“汇聚”的,同一个 -31 可能对应多种根因,必须结合时间戳、网络、服务状态综合判断。第二,把时间同步这件事写进交付 checklist。不管是给新员工培训,还是给新机器上线,都明确一条:启用 NTP,设置正确的时区。第三,注意办公网防火墙对 NTP 端口 123 的策略。很多内网限制了这个端口,导致自动同步失败。提前找网络管理员确认,能省掉后面大量隐蔽问题。第四,如果有多台许可证服务器做高可用,所有服务器之间的时间容差也要校验。客户端和主服务器同步了,但备用服务器时间不对,故障切换之后照样报 -31。
我在实际工作中感受最深的一点是:这种问题往往不是“技术难度高”,而是“太隐蔽”。少有人会怀疑一台刚装好的服务器时区是错的,也没有人每天盯着系统时间看。但只要你把时间基线统一了,把排查路线固定下来,这套麻烦就能彻底从日常清单里划掉。