“许可不够”这四个字,从工程师嘴里说出来和从服务器日志里读出来,经常不是一回事。工程师说的是“我现在点了没反应”,日志说的是“池子里确实满了”。但池子为什么满,跟池子该不该满,中间隔着至少三层东西。
工业软件的浮动许可,大部分底层跑的是 FlexNet(现在叫 FlexNet Publisher),SolidWorks 的 SNL、NX 的 SPLM、ANSYS 那一套都是。FlexNet 的基本逻辑很简单:客户端启动软件,向 license server 发 checkout 请求,vendor daemon 从池子里切一块出来,绑在当前这个会话上。正常退出才 checkin,崩溃、休眠、强杀进程、网络闪断,都不触发归还。默认情况下,一个“非活跃”的 checkout 可以在服务器上挂大概两个小时才释放,有些版本还得靠 TIMEOUTALL 才能把这个时间压下来。
这就是第一个要认清的事实:FlexNet 判断的是“会话还在不在”,不是“人还在不在”。 你开着 CATIA 去开三个会,它认为你在用;你笔记本从 WiFi 切到 VPN,IP 变了,FlexNet 认为原会话死了,回收,客户端重连,再 checkout 一次——你明明只开了一个软件,池子里少了两把。这不是 bug,是协议设计使然。
先看拒绝发生在哪个 feature 上。 lmutil lmstat -a 的输出里,每个 feature 单独一行,Total of X licenses available 下面是当前 checkout 的人、主机、handle 值。拒绝率高的那个 feature,往往不是“总量最少”的那个,而是“被占用方式最烂”的那个。你买了两百个 MD2,但 GSD 只有二十个,结构工程师一窝蜂把 GSD 也勾上,那 GSD 的拒绝率必然难看,跟 MD2 总量没关系。
再看占用时长分布,不是看总量。 平均使用率 55% 不代表没事。如果每天上午十点到十一点、下午两点到四点持续贴到 95%,工程师体感就是“永远抢不到”。你要看的是高占用时段的持续时间,以及在这个时段里,有多少 checkout 是超过两小时没有实际键鼠活动的。
检查 borrowing 有没有把池子掏空。 FlexNet 的离线借用(borrowing)在 server 面板上只显示“被借出”,不显示“借给谁、什么时候还”。有人借了三十天的 SolidWorks 出去,回来不还,池子里就永久少一把,直到借用期结束或者有人去注册表里把 HKEY_CURRENT_USER\Software\FLEXlm License Manager\Borrow 改名清掉。这东西不查,你永远算不对可用量。
VPN 用户的僵尸会话单独算。 远程办公的人切网络、切 IP,产生的僵尸 checkout 会吃掉名额,默认两小时才自己释放。如果你的研发团队有相当比例在 VPN 上,池子的“名义空闲量”和“实际可 checkout 量”之间有一个稳定的缺口,这个缺口不是买 license 能填的,得靠超时和会话管理来收。
第一步,把 lmstat 的输出定时落盘,先攒一周数据。 不要只看某一天、某一个时刻。命令本身不复杂:
text
lmutil lmstat -c 27000@lic-srv -a > D:\audit\lm_YYYYMMDD.log每天上班高峰、午休、下班前各抓一次,或者直接写个计划任务每小时跑一次。一周之后你手里有了每个 feature 的峰值、低谷和持续高占用窗口,才有资格谈“到底缺不缺”。
第二步,把 TIMEOUT 配起来,但别一刀切。 FlexNet 的 options 文件(.opt)挂在 license 文件的 VENDOR 行后面,写 TIMEOUTALL 1800 表示任意会话三十分钟无活动就回收。注意两点:最小生效值是 900 秒,写 600 不报错但不生效;改完要 lmreread 让 daemon 重读配置。CAE 求解、NX 刀路计算这类“键鼠不动但 CPU 在跑”的场景,先别急着全覆盖 TIMEOUTALL,用 feature 级的 TIMEOUT 单独放过,或者把计算节点放进 exclude 组。
第三步,用 GROUP / RESERVE / MAX 把池子的形状修一修。 还是 options 文件里,GROUP core_design 圈出核心设计组,RESERVE 6 SW_SIM USER_GROUP sim_node 给仿真节点留底,MAX 42 SW_PREMIUM USER_GROUP core_design 防止核心组里有人开多实例吞位。这些不是买 license,是把你已经付过钱的东西重新切一刀,让稀缺模块不被非目标用户顺手拿走。

第四步,lmremove 只当急救用,别当常规武器。 lmutil lmremove <feature> <user> <host> <display> 可以踢掉一个卡死的 checkout。但 lmadmin 默认是关掉 lmremove 的,要加 -allowLicenseReclaim 启动才能用。更重要的是,lmremove 不区分“卡死”和“正在存盘”,误杀一次就够你写事故报告。常规回收靠 TIMEOUT,lmremove 留给那些 TIMEOUT 都收不掉的僵尸。
如果你只有一台 license server、一两个 FlexNet 产品,上面这套 lmstat 加 options 文件加计划任务,足够把这一轮“抢不到”压下去。OpenLM 这类旁路监控工具的价值在于:它能持续解析 FlexNet 报文,把 checkout 事件、拒绝记录、borrow 归还、空闲时长归集到一个视图里,不用你每天手工去扒日志。但如果你连自己池子里有几个 feature、哪些人在借、哪些会话在僵尸挂着都还没搞清楚,上工具只是把糊涂账搬到另一个界面上,本质上没有区别。
华东一家做汽车零部件的企业,SolidWorks 买了五十个 Premium 浮动,研发那边照样天天喊不够。IT 没急着打增购申请,先跑了两周 lmstat,顺手用 quser 交叉看 RDP 会话的空闲时间。结果出来挺难看:日均峰值占用四十六个,但真正有键鼠活动的只有四成左右,纯闲置超过二十分钟的占了将近一半。有个仿真岗的兄弟提交完算例就切走去开会,checkout 挂了一下午;还有两台外包机的账号绑死在旧机器上,人早就不在了,license 一直占着。他们干的事不复杂:options 文件里挂 TIMEOUTALL 1800,给仿真节点单独 RESERVE,把外包机的僵尸账号从 AD 里停掉。没加买一个 license,三周之后高峰期的拒绝次数从每天十几次掉到个位数。后来那个 IT 主管说了一句话:你不是缺许可证,你是缺一个“谁在占着、占着干嘛”的答案。