From 2bca7264182593c3dbe5e9d1215fe7418ccfe91f Mon Sep 17 00:00:00 2001 From: xxm Date: Wed, 5 Aug 2026 15:23:00 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20market=5Fwatch/mr=5Fscanner/s2=5Fscanner?= =?UTF-8?q?=20=E7=BB=9F=E4=B8=80=E5=8A=A0=E8=A3=85=E8=87=AA=E6=84=88?= =?UTF-8?q?=E5=BC=8F=E5=8D=95=E4=BE=8B=E5=AE=88=E5=8D=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 与price_monitor同模式: 新鲜实例在跑则退出, 卡死超时则SIGKILL接管 - market_watch 600s / 扫描器 1500s 阈值 - 落实2026-08-05重型任务资源约束铁律第4条 --- deploy/profile-scripts/market_watch.py | 34 ++++++++++++++++++++++++++ deploy/profile-scripts/mr_scanner.py | 33 +++++++++++++++++++++++++ deploy/profile-scripts/s2_scanner.py | 33 +++++++++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/deploy/profile-scripts/market_watch.py b/deploy/profile-scripts/market_watch.py index cc8ad153..f76f6d11 100644 --- a/deploy/profile-scripts/market_watch.py +++ b/deploy/profile-scripts/market_watch.py @@ -155,7 +155,41 @@ def get_danger_sectors(sectors, top_n=3): # ── 主流程 ── +def _singleton_guard(max_age_sec, script_tag): + """自愈式单例守卫(2026-08-05 进程堆积事故后统一加装)""" + import subprocess as _sp, os as _os, sys as _sys + my_pid = _os.getpid() + try: + out = _sp.run(["ps", "-C", "python3", "-o", "pid,etimes,cmd"], + capture_output=True, text=True, timeout=10).stdout + for line in out.splitlines(): + if script_tag not in line: + continue + parts = line.split(None, 2) + if len(parts) < 3: + continue + try: + pid = int(parts[0]); age = int(parts[1]) + except ValueError: + continue + if pid == my_pid: + continue + if age > max_age_sec: + try: + _os.kill(pid, 9) + print(f"[guard] SIGKILL卡死实例 pid={pid} age={age}s", flush=True) + except ProcessLookupError: + pass + else: + print(f"[guard] 已有新鲜实例 pid={pid} age={age}s 在跑, 本实例退出", flush=True) + _sys.exit(0) + except Exception as _e: + print(f"[guard] 守卫异常(放行): {_e}", flush=True) + + def main(): + # 行業板塊 + _singleton_guard(600, "market_watch.py") # 行業板塊:EM → THS → 兜底 sectors = fetch_sector_em() source = "eastmoney" diff --git a/deploy/profile-scripts/mr_scanner.py b/deploy/profile-scripts/mr_scanner.py index 75c18e31..22e4c3d1 100644 --- a/deploy/profile-scripts/mr_scanner.py +++ b/deploy/profile-scripts/mr_scanner.py @@ -284,8 +284,41 @@ def check_vmr(klines, mkt_adx=None): } +def _singleton_guard(max_age_sec, script_tag): + """自愈式单例守卫(2026-08-05 进程堆积事故后统一加装)""" + import subprocess as _sp, os as _os, sys as _sys + my_pid = _os.getpid() + try: + out = _sp.run(["ps", "-C", "python3", "-o", "pid,etimes,cmd"], + capture_output=True, text=True, timeout=10).stdout + for line in out.splitlines(): + if script_tag not in line: + continue + parts = line.split(None, 2) + if len(parts) < 3: + continue + try: + pid = int(parts[0]); age = int(parts[1]) + except ValueError: + continue + if pid == my_pid: + continue + if age > max_age_sec: + try: + _os.kill(pid, 9) + print(f"[guard] SIGKILL卡死实例 pid={pid} age={age}s", flush=True) + except ProcessLookupError: + pass + else: + print(f"[guard] 已有新鲜实例 pid={pid} age={age}s 在跑, 本实例退出", flush=True) + _sys.exit(0) + except Exception as _e: + print(f"[guard] 守卫异常(放行): {_e}", flush=True) + + def main(): force = "--force" in sys.argv + _singleton_guard(1500, "mr_scanner.py") top_n = TOP_N if "--top" in sys.argv: try: diff --git a/deploy/profile-scripts/s2_scanner.py b/deploy/profile-scripts/s2_scanner.py index 884a7833..50c26cdc 100644 --- a/deploy/profile-scripts/s2_scanner.py +++ b/deploy/profile-scripts/s2_scanner.py @@ -103,8 +103,41 @@ def check_s2(klines): } +def _singleton_guard(max_age_sec, script_tag): + """自愈式单例守卫(2026-08-05 进程堆积事故后统一加装)""" + import subprocess as _sp, os as _os, sys as _sys + my_pid = _os.getpid() + try: + out = _sp.run(["ps", "-C", "python3", "-o", "pid,etimes,cmd"], + capture_output=True, text=True, timeout=10).stdout + for line in out.splitlines(): + if script_tag not in line: + continue + parts = line.split(None, 2) + if len(parts) < 3: + continue + try: + pid = int(parts[0]); age = int(parts[1]) + except ValueError: + continue + if pid == my_pid: + continue + if age > max_age_sec: + try: + _os.kill(pid, 9) + print(f"[guard] SIGKILL卡死实例 pid={pid} age={age}s", flush=True) + except ProcessLookupError: + pass + else: + print(f"[guard] 已有新鲜实例 pid={pid} age={age}s 在跑, 本实例退出", flush=True) + _sys.exit(0) + except Exception as _e: + print(f"[guard] 守卫异常(放行): {_e}", flush=True) + + def main(): force = "--force" in sys.argv + _singleton_guard(1500, "s2_scanner.py") top_n = TOP_N if "--top" in sys.argv: try: