| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- """
- ftp_upload.py - 将本地部署目录通过 FTP 上传到服务器。
- 可被 artifacts.py 调用,也可在 pipeline.py 中独立使用。
- """
- import ftplib
- import os
- import logging
- from pathlib import Path
- from typing import Optional
- logger = logging.getLogger(__name__)
- class FTPUploadError(Exception):
- """FTP 上传异常"""
- pass
- def upload_directory(cfg, local_dir: str) -> None:
- """
- 将本地目录递归上传到 FTP 服务器。
- Args:
- cfg: PipelineConfig 对象,包含 FTP 连接信息与 ftp_root 路径。
- local_dir: 本地待上传目录路径(如 .../HORIZON/J6B/AD26IDV01/xxx/deploy_dir)
- """
- local_path = Path(local_dir)
- if not local_path.is_dir():
- raise FTPUploadError(f"Local upload directory not found: {local_dir}")
- # 目标 FTP 根路径:DB-年/FTP_ROOT,与原 shell 一致
- import datetime
- ftp_root = f"DB-{datetime.datetime.now().year}/{cfg.ftp_root}"
- logger.info("Connecting to FTP %s:%d", cfg.ftp_host, cfg.ftp_port)
- ftp = ftplib.FTP()
- try:
- ftp.connect(host=cfg.ftp_host, port=cfg.ftp_port, timeout=30)
- ftp.login(user=cfg.ftp_user, passwd=cfg.ftp_password)
- ftp.set_pasv(True) # 被动模式
- _mkdir_p(ftp, ftp_root) # 确保远端根目录存在
- _upload_recursive(ftp, local_path, ftp_root)
- logger.info("FTP upload completed successfully: %s -> %s", local_dir, ftp_root)
- except ftplib.all_errors as e:
- raise FTPUploadError(f"FTP upload failed: {e}") from e
- finally:
- try:
- ftp.quit()
- except Exception:
- pass
- def _mkdir_p(ftp: ftplib.FTP, remote_path: str) -> None:
- """递归创建远端目录,类似 mkdir -p"""
- dirs = remote_path.strip('/').split('/')
- current = ''
- for d in dirs:
- current += f"/{d}"
- try:
- ftp.cwd(current)
- except ftplib.error_perm:
- ftp.mkd(current)
- ftp.cwd(current)
- def _upload_recursive(ftp: ftplib.FTP, local_path: Path, remote_dir: str) -> None:
- """递归上传文件与子目录"""
- ftp.cwd(remote_dir)
- for item in local_path.iterdir():
- remote_full = f"{remote_dir}/{item.name}"
- if item.is_file():
- with open(item, 'rb') as f:
- ftp.storbinary(f'STOR {item.name}', f)
- logger.debug("Uploaded file: %s", remote_full)
- elif item.is_dir():
- _mkdir_p(ftp, remote_full)
- _upload_recursive(ftp, item, remote_full)
- else:
- logger.warning("Skipping non-regular file: %s", item)
|