diff --git a/deploy/profile-scripts/price_monitor.py b/deploy/profile-scripts/price_monitor.py index 652e1d9e..b5159d11 100644 --- a/deploy/profile-scripts/price_monitor.py +++ b/deploy/profile-scripts/price_monitor.py @@ -407,10 +407,17 @@ def _handle_sigterm(signum, frame): _cleanup_lock() sys.exit(0) +def _handle_sigalrm(signum, frame): + """收到SIGALRM强制超时时清理锁文件后退出""" + _cleanup_lock() + print(f"[TIMEOUT] 本轮执行超时({signum}s),已清理锁文件", file=sys.stderr, flush=True) + sys.exit(0) + def run_once(round_label=""): """执行一轮完整的监控流程""" import os, signal # 必须在开头import,否则os变量会被后面的局部import绑定覆盖 signal.signal(signal.SIGTERM, _handle_sigterm) + signal.signal(signal.SIGALRM, _handle_sigalrm) os.nice(10) # 降低优先级,避免与DB其他写操作抢占 # ── 进程锁:同一时间只跑一个实例 ── _lk = "/tmp/price_monitor.lock" @@ -425,6 +432,7 @@ def run_once(round_label=""): pass with open(_lk, "w") as _f: _f.write(str(os.getpid())) + signal.alarm(120) # 硬上限120s,超时自动清理锁退出 label = f" [{round_label}]" if round_label else "" start = time.time() @@ -745,6 +753,9 @@ def run_once(round_label=""): # 输出耗时 print(f"⏱{label} {elapsed:.1f}s", flush=True) + # 取消超时定时器(正常完成) + signal.alarm(0) + # 清理进程锁 try: os.remove("/tmp/price_monitor.lock")