# relisten 沉降段原语化受阻的确定性复现:连续快速 STOR(无间隔),统计 425/超时失败次数 # 用法: python n30_repro.py [--host IP] [--user U --pwd P] [--n 10] [--size 1024] # 退出码: 0=全部成功 / 1=有失败 / 2=连接错误 import argparse import io import sys from ftplib import FTP, error_temp, error_perm def main(): ap = argparse.ArgumentParser() ap.add_argument("--host", default="192.168.1.100") ap.add_argument("--port", type=int, default=21) ap.add_argument("--user", default=None, help="None=anonymous") ap.add_argument("--pwd", default=None) ap.add_argument("--n", type=int, default=10) ap.add_argument("--size", type=int, default=1024) args = ap.parse_args() data = b"X" * args.size fails = [] try: f = FTP() f.connect(args.host, args.port, timeout=15) if args.user is None: f.login("anonymous", "x@x") else: f.login(args.user, args.pwd) f.voidcmd("TYPE I") for i in range(args.n): name = "n30_%02d.tmp" % i try: with io.BytesIO(data) as b: f.storbinary("STOR " + name, b) print("STOR #%02d OK" % (i + 1)) except (error_temp, error_perm, OSError, EOFError) as e: print("STOR #%02d FAIL %r" % (i + 1, e)) fails.append(i + 1) # 会话可能已重启:尝试重登继续计数 try: f.quit() except Exception: pass try: f = FTP() f.connect(args.host, args.port, timeout=15) if args.user is None: f.login("anonymous", "x@x") else: f.login(args.user, args.pwd) f.voidcmd("TYPE I") except Exception as e2: print("re-login failed: %r" % e2) break # 清理 try: for i in range(args.n): try: f.delete("n30_%02d.tmp" % i) except Exception: pass f.quit() except Exception: pass except Exception as e: print("connect error: %r" % e) return 2 print("RESULT: %d/%d failed %s" % (len(fails), args.n, fails)) return 1 if fails else 0 if __name__ == "__main__": sys.exit(main())