使用Python定时清理运行超时的pdflatex僵尸进程

问题

在我们之前的《基于texlive定制chemfig化学式转换Python服务镜像》定制的pdflatex在线转换的镜像已经运行在生产环境了,但是最近总有人反馈服务跑着跑着就慢了,本来一秒内能出结果的数据,居然用了十几秒,遂受不了了

分析与定位

pdflatex执行了texlive的转换命令,此命令执行cpu单核瞬间会拉致近100%,然后在瞬间恢复,之前测试过相对复杂的表达式,执行时间应当都会在2秒内结束,于是通过kubectl进入pod里面看下情况,ps发现有些驻留的pdflatex进程,有许多已经运行了几小时到几天不等变成僵尸进程了,kill之后服务立马恢复,但是运行几天又会出现,texlive咱也不熟,手动调用也复现不了,决定迂回解决。

方案有二:
1、设置命令超时时间,过期杀死
2、定时轮询pdflatex进程,超过30秒直接干掉
容器环境下是基于alpine linux,超时用的subprocess.Popen方式实现,但是open里的cmd就是不执行,永远timeout,不知咋回事,时间紧,问题严重本次解决是同构第二种方式实现的

解决

每一分钟检查一下进程列表,获取pdflatex相关进程,判断其运行时间,超过30秒则直接kill,代码如下:

import time
import psutil
import sched
import logging

schedule = sched.scheduler(time.time, time.sleep)
logging.basicConfig(level=logging.DEBUG, 
                    filename='schedule.log',
                    filemode='a', 
                    format=
                    '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
                    )


def process_checker(inc):
    currentTime = time.time()
    logging.info("pdflatex进程检查……")
    pids = psutil.pids()
    for pid in pids:
        p = psutil.Process(pid)
        if p.name().find("pdflatex") > -1:
            print(p.create_time())
            p.create_time()
            second = currentTime - p.create_time()
            if second > 30:
                logging.info("进程运行超时:" + str(second) + "秒,关闭进程,进程名称:" + p.name())
                p.terminate()
            else:
                logging.info("进程运行时间:" + str(second) + "秒,进程名称:" + p.name())
    schedule.enter(inc, 0, process_checker, (inc,))


def timerRunner(inc=60):
    schedule.enter(0, 0, process_checker, (inc,))
    schedule.run()


timerRunner(60)

if __name__ == '__main__':
    print("启动进程清理任务")

修改启动脚本,把这个schedule一起启动即可

posted @ 2021-07-31 23:57  蒲公英的狂想  阅读(281)  评论(2编辑  收藏  举报