GitLab CI运行Python FTPS上传脚本出现连接超时该如何解决
问题原因定位及解决办法
核心问题排查方向
- 首先确认GitLab Runner的网络出口权限:大部分公有GitLab Runner的出口IP不固定,如果你的FTP服务器配置了IP白名单,会直接拦截连接请求导致超时;如果是自建GitLab Runner,需要检查Runner所在服务器的出站防火墙规则是否允许访问FTP服务器的对应端口,以及FTP被动模式的随机端口段。
- 其次确认FTPS端口配置是否正确:Python的
ftplib.FTP_TLS默认使用显式FTPS的21端口,如果你用的是隐式FTPS,需要手动指定端口为990。 - 第三检查FTPS模式适配:Windows本地环境默认适配被动模式,但GitLab Runner的容器环境可能因为NAT/防火墙规则,主动模式无法建立数据连接,需要强制开启被动模式。
具体调整方案
1. 先验证网络连通性
修改.gitlab-ci.yml添加连通性测试步骤,先确认Runner能否正常访问FTP服务:
image: python:latest deploy: stage: deploy script: # 替换<ftp服务器地址>和<端口>为你的实际配置 - apt-get update && apt-get install -y netcat - nc -zv <ftp服务器地址> <端口> - python ftpupload.py only: - main
如果nc测试步骤超时,说明是网络层问题,将GitLab Runner的出口IP段添加到FTP服务器的白名单即可。
2. 调整Python FTP脚本配置
修改连接代码,强制开启被动模式,添加调试日志,适配不同FTPS类型:
class ReusedSslSocket(ssl.SSLSocket): def unwrap(self): pass class MyFTP_TLS(ftplib.FTP_TLS): """Explicit FTPS, with shared TLS session""" # 如果是隐式FTPS,添加以下初始化逻辑 # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # self._sslobj = self.context.wrap_socket(self.sock, server_hostname=self.host) def ntransfercmd(self, cmd, rest=None): conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest) if self._prot_p: conn = self.context.wrap_socket(conn, server_hostname=self.host, session=self.sock.session) # reuses TLS session conn.__class__ = ReusedSslSocket # we should not close reused ssl socket when file transfers finish return conn, size # 开启调试日志,方便定位连接问题 ftplib.FTP_TLS.debugging = 2 # 显式指定端口,显式FTPS填21,隐式FTPS填990 session = MyFTP_TLS(server, port=21, user=username, passwd=password, timeout=60) # 强制开启被动模式 session.set_pasv(True) session.prot_p()
3. 额外优化建议
- 不要把FTP地址、账号、密码硬编码在脚本中,存储到GitLab项目的CI/CD变量中,通过环境变量读取,避免敏感信息泄露。
- 可以根据实际网络情况适当调大timeout参数,避免网络波动导致的偶发连接失败。
内容的提问来源于stack exchange,提问作者ionosphere
相关产品推荐
相关产品推荐

