| 2891 | |
| 2892 | |
| 2893 | class _ScriptService: |
| 2894 | _redirection_regexp = re.compile(r"\s+>\s+") |
| 2895 | |
| 2896 | def __init__(self): |
| 2897 | self.heap: List[Tuple[int, int, _Script]] = [] |
| 2898 | self.lock = threading.Lock() |
| 2899 | self._my_pid = os.getpid() |
| 2900 | self._tasks: List[_Script] = [] |
| 2901 | |
| 2902 | def register(self, name: str, cmd: str, interval: int): |
| 2903 | """注册任务""" |
| 2904 | task = _Script(name, cmd, interval) |
| 2905 | self._tasks.append(task) |
| 2906 | return task |
| 2907 | |
| 2908 | def register_scripts(self, *scripts: _Script): |
| 2909 | """注册任务""" |
| 2910 | for script in scripts: |
| 2911 | if script in self._tasks: |
| 2912 | continue |
| 2913 | self._tasks.append(script) |
| 2914 | |
| 2915 | def init_tasks(self): |
| 2916 | """添加任务到队列""" |
| 2917 | with self.lock: |
| 2918 | for idx, task in enumerate(self._tasks): |
| 2919 | next_execution_time = task.first() + idx*3 |
| 2920 | heapq.heappush(self.heap, (next_execution_time, task.get_ident(), task)) |
| 2921 | self._tasks = None |
| 2922 | |
| 2923 | def repetition_check(self, task: _Script) -> bool: |
| 2924 | real_cmd = task.cmd.strip() |
| 2925 | if real_cmd.startswith("nohup"): |
| 2926 | real_cmd = real_cmd[len("nohup"):].strip() |
| 2927 | if self._redirection_regexp.search(real_cmd): |
| 2928 | # 切分重定向 |
| 2929 | real_cmd = self._redirection_regexp.split(real_cmd)[0].strip() |
| 2930 | |
| 2931 | real_cmd_list = real_cmd.split(" ") |
| 2932 | for p in psutil.pids(): |
| 2933 | try: |
| 2934 | if p == self._my_pid: |
| 2935 | continue |
| 2936 | proc = psutil.Process(p) |
| 2937 | cmd = proc.cmdline() |
| 2938 | if cmd[:len(real_cmd_list)] != real_cmd_list: |
| 2939 | continue |
| 2940 | |
| 2941 | run_times = time.time() - proc.create_time() |
| 2942 | if run_times < task.interval: |
| 2943 | write_log("任务[{}]未达到运行间隔,跳过".format(task.name)) |
| 2944 | return False |
| 2945 | if run_times < 10 * 60: |
| 2946 | write_log("任务【{}】执行拥塞,跳过本次执行".format(task.name), _level='error', color='red') |
| 2947 | return True |
| 2948 | else: |
| 2949 | write_log("任务【{}】执行超时,已杀死".format(task.name), _level='error', color='red') |
| 2950 | proc.kill() |
no outgoing calls
no test coverage detected