python通过psutil判断当前脚本重复运行杀掉原进程
crontab执行python脚本,如果周期内未执行完毕,会新开一个进程执行,会导致重复执行,大部分情况下需要避免这种情况
python中可以通过psutil获取所有进程信息,筛选出当前脚本,杀进程时需要先杀子进程,但子进程不能使用os.killpg(windows下运行.bat
会有问题)
kill_exist_task
代码如下:
import os
import platform
import signal
import sys
import psutil
def kill_exist_task(filter_last_arg: str = ''):
# 判断windows
isWindows = platform.system() == "Windows"
# py文件名
py_file = sys.argv[0].split('/')[-1]
if isWindows:
py_file = sys.argv[0].split('\\')[-1]
print("kill_exist_task", sys.argv, py_file, filter_last_arg)
# 查找进程
for proc in psutil.process_iter():
cmd = []
try:
cmd = proc.cmdline()
except Exception as e:
pass
proc_cmd = " ".join(cmd)
# 匹配cmd进程: (D:\Python38\python.exe D:\scrap\grab.py 或 D:\Python38\python.exe grab.py 或 python.exe grab.py)
if not (proc_cmd.__contains__("python") and proc_cmd.__contains__(py_file)):
continue
print(" -- 匹配到cmd: ", proc.pid, proc_cmd)
# 查找相同基础并排除当前进程
if os.getpid() == proc.pid:
print(" -- 是当前进程: ", os.getpid(), proc.pid)
continue
print(" -- 不是当前进程: ", os.getpid(), proc.pid)
# 过滤最后一个参数,如`python3 grab.py 2002`的 2002 (如需过滤其他参数,自行调整)
if (not filter_last_arg) or (filter_last_arg and cmd[-1] == filter_last_arg):
print(" -- 筛选出进程: py_file=%s,filter_last_arg=%s,pid=%s,cmd=%s" % (py_file, filter_last_arg, proc.pid, proc_cmd))
try:
# 终止子进程(可能通过shell或其他方式调起其他独立进程)
pp = psutil.Process(proc.pid)
for sub in pp.children(recursive=True):
print(" -- 终止子进程: %s %s" % (sub.name(), sub.pid))
# 子进程不能使用os.killpg(windows下运行`.bat`会有问题)
sub.terminate()
sub.kill()
# 终止当前进程
proc.terminate()
proc.kill()
os.killpg(proc.pid, signal.SIGKILL)
print(" -- 终止主进程: terminate %s" % proc.pid)
except Exception as e:
pass
print('kill_exist_task done')