找到节点上占用工作空间的进程及进程打开的文件,并且释放文件占用,保证清理工作空间成功

"""
* 模块名  : clear_occupy.py
* 函数功能: 清理占用工作空间的进程,避免流水线出错,只应用于windows节点。linux不需要
"""
import os
import signal
import subprocess
import sys
import traceback

import chardet
import psutil


def release_opened_file(process_id, file_name):
    print(f"开始释放{process_id}对文件{file_name}的占用")
    cur_dir = os.path.dirname(os.path.abspath(__file__))
    try:
        cmd = f"{cur_dir}/handle64.exe /s /accepteula"
        ret, info = run_shell(cmd)
        if ret:
            print(f"静默安装失败:{info}")
        cmd = f"{cur_dir}/handle64.exe /v -nobanner {file_name}"
        ret, info = run_shell(cmd)
        if ret:
            print(f"获取{file_name}的handle失败")
        file_handles = info.split("\r\n")[1:-1]
        os.chdir(cur_dir)
        for h in file_handles:
            pid = h.split(",")[1]
            handle = h.split(",")[3]
            if int(pid) == int(process_id):
                cmd = f"echo y|handle64.exe -nobanner -p {process_id} -c {handle}"
                ret, info = run_shell(cmd)
                if ret:
                    print(f"解除占用失败")
    except Exception as e:
        print(traceback.format_exc())


def run_shell(cmdline, env=None):
    handle = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, env=env)
    data = b""
    while True:
        line = handle.stdout.readline()
        if not line:
            break
        # print(line)
        data += line
    ret_code = handle.wait()
    if not data:
        return ret_code, data
    charset = chardet.detect(data)["encoding"]
    if charset.lower() == "gb2312":
        charset = "gbk"
    data_str = data.decode(encoding=charset)
    # print("%s -- cost %d s" % (cmdline, (time.time() - time_begin)))
    return ret_code, data_str


def clear_occupy_processes(workspace):
    processes = []
    for process in psutil.process_iter():
        processes.append(process)
    print(len(processes))
    count = 0
    for process in processes:
        count += 1
        # print(count)
        try:
            proc_info_dict = process.as_dict(attrs=["pid", "name", "cmdline", "cwd"])
            print(f"-----{proc_info_dict}-----")
            p = psutil.Process(pid=proc_info_dict["pid"])
            if "remoting.jar" in proc_info_dict["cmdline"] and proc_info_dict["name"] == "java.exe":
                for f in p.open_files():
                    print(f"opened files: {f[0]}")
                    if workspace in f[0]:
                        release_opened_file(proc_info_dict["pid"], f[0])
            if proc_info_dict["cmdline"] and is_ws_in_cmdline(workspace, proc_info_dict["cmdline"]):
                # print(proc_info_dict)
                if "clear_occupy.py" in proc_info_dict["cmdline"][-2]:
                    print("不清理clear_occupy.py")
                    continue
                if "jenkins-main.bat" in proc_info_dict["cmdline"][-1]:
                    print("不清理jenkins-main.bat")
                    continue
                if "jenkins-wrap.bat" in proc_info_dict["cmdline"][-1]:
                    print("不清理jenkins-wrap.bat")
                    continue
                os.kill(proc_info_dict["pid"], signal.SIGINT)
            elif proc_info_dict["cwd"] and workspace in proc_info_dict["cwd"]:
                print(proc_info_dict)
                os.kill(proc_info_dict["pid"], signal.SIGINT)
        except Exception as e:
            print(e)
        if count == len(processes):
            break
    print("清理完占用进程")
    sys.exit(0)


def is_ws_in_cmdline(ws, cmdline):
    if cmdline:
        for cmd in cmdline:
            if ws in cmd:
                return True


if __name__ == '__main__':
    workspace = sys.argv[1]
    workspace = workspace.replace("/", "\\")
    print(f"workspace:{workspace}")
    clear_occupy_processes(workspace)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值