diff --git a/tests/test_svc_recover.py b/tests/test_svc_recover.py index f411d04b..3d32e843 100644 --- a/tests/test_svc_recover.py +++ b/tests/test_svc_recover.py @@ -453,8 +453,23 @@ class SvcAutoRecoverTests(unittest.TestCase): s.close() return False + def _ss_can_attribute_pid(self): + """reclaim_own_port /「非本服务」归因依赖 ss -ltnp 的 pid= 字段。 + + CI 容器常无 iproute2 或 ss 不带进程信息——此时只能探测占用、不能归因, + 相关用例跳过(拒绝启动的兜底路径仍由「未能识别占用者」覆盖)。 + """ + try: + out = subprocess.run( + ["ss", "-ltnp"], capture_output=True, text=True, timeout=5) + except (FileNotFoundError, OSError, subprocess.TimeoutExpired): + return False + return out.returncode == 0 and "pid=" in out.stdout + def test_start_reclaims_own_orphan_without_pidfile(self): """模拟 update 误清 pidfile 后本 bin 仍占口:裸 start 应回收并拉起新进程。""" + if not self._ss_can_attribute_pid(): + self.skipTest("ss -ltnp 无法归因 PID(reclaim_own_port 需此能力)") port = 18812 self.seed_agent("dev", port) self.start_ok("dev") @@ -486,7 +501,11 @@ class SvcAutoRecoverTests(unittest.TestCase): try: result = self.svc("dev", "start", check=False) self.assertEqual(result.returncode, 1, result.stdout) - self.assertIn("非本服务", result.stdout) + # 有 ss 时归因到外部进程 →「非本服务」;无 ss 时仅能探测 →「未能识别占用者」。 + # 两种路径都拒绝启动,不拉起本服务。 + self.assertTrue( + ("非本服务" in result.stdout) or ("未能识别占用者" in result.stdout), + result.stdout) self.assertFalse(self.pid_alive(self.pid_of("dev"))) finally: thief.terminate()