整理云盘旧资料,翻出2018年第一次写自动释放许可脚本的原始代码,现在看写得又笨又冗余,居然当时还能用。
那会儿我刚干这行没多久,公司用的还是某款机械设计软件的浮动许可,常年被投诉许可不够用。我去网上搜了一圈没找到现成的自动回收工具,就想着自己写一个。那两周我基本没怎么睡好觉,每天晚上哄完孩子就开始对着屏幕敲代码,连熬了两个通宵。我记得第三天凌晨五点多脚本第一次跑成功把闲置会话踢掉的时候,整个人靠在椅背上长出一口气,眼睛酸得直流泪。但那会儿水平实在太菜了,代码里全是if套if,路径写死、服务器地址写死、连超时时间都直接嵌在循环里,换个环境就得从头改。最离谱的是连命令行输出的解析用的是split字符串手工数位置,FlexNet输出多一个空格整行就废了。就这种水平的代码,当时居然还跑了快半年没出过大问题,想想真是运气好。
后来这些年我陆陆续续把这套东西重写了七八遍,慢慢磨出来一套现在用得挺顺的版本。利用率从最早的三成左右拉到了现在的八成上下,核心其实就是把"自动回收"这个开关真正做活了,让它自己跑不用人盯着。
第一件事是把所有硬编码的东西全部抽出来放到配置文件里。服务器的IP地址、日志路径、每个Feature的阈值时间、白名单用户组,全部写到一个独立的config.ini里,脚本每次启动去读这个文件。万一哪天换服务器或者改阈值了,直接改配置文件就行,不用碰代码。当年那个老脚本踩过的最蠢的一个坑,我把FlexNet的服务器地址写死在了代码里,后来服务器换过一次IP,我忘了同步改脚本里的地址,结果脚本跑了整整一周我都没发现它在连一个已经不存在的IP,每周自动释放一直没生效,还以为是闲置会话变少了,直到有同事来问我"最近回收是不是坏了"我才反应过来。那之后我就再也不把任何环境相关的参数写死在代码里了。
第二件事是把命令输出的解析换成了更鲁棒的方式。以前我是用字符串split按空格分割,然后取固定位置的字段,FlexNet输出稍微多个空格或者版本号变一下顺序就全乱了。后来我发现FlexNet可以输出json格式,调用的时候加个参数就直接返回结构化的数据,我直接用json库解析,省去了各种正则和字符串切分。当年踩过的一个坑是,我在解析lmstat输出的时候,有一行Feature的描述里自带空格,我用空格分割就直接把那一行拆成了七八段,后面的所有字段位置全错位了。我花了一个晚上才想明白为什么那个Feature永远显示的是别人的用户名,就因为那个该死的空格。

第三件事是把回收逻辑加了双条件判定。原来我的脚本是只要有会话空闲超过阈值就直接回收,后来发现仿真组的人经常设置完任务去开会,键鼠不动但CPU在跑,按原来的逻辑全给踢了。现在的版本是同时检测两个条件:键鼠空闲时间超过阈值并且CPU占用率低于5%,只有两个条件同时满足才执行回收。任何一边不满足就跳过。当年有个特别坑的事,我写好脚本上线第一周,一切正常,结果第二周某天下午突然收到一堆投诉,说他们做长仿真的任务被踢了。我查了半天的日志才发现,那几台机器键鼠确实是闲置了,但CPU全程满着在跑计算,我的脚本没判断CPU直接给回收了。从那以后我再也没用过一维判定。
最后说两个我现在常用的不用写复杂代码就能实现自动管理的懒人方法。第一个是直接用FlexNet自带的TIMEOUT选项,在option文件里配一行配置,服务自己就会在指定时间后回收闲置的会话,根本不用写脚本。这个功能很多人不知道或者不敢用,但实测稳定得很,唯一的缺点是不能做CPU判定,只能按时间一刀切。第二个是用Windows或者Linux的计划任务定时调用FlexNet自带的lmremove命令,把空闲会话列表重定向到一个文件里,然后脚本里用简单的grep和awk过滤一下,比从头写一个完整的Python脚本省事太多了,几行shell就搞定。
把那堆2018年的老代码打包扔到一个叫"archive_old"的文件夹里,新版的放外面日常用。亲测好使,这周已经帮3个同事解决了同款问题。