FTP同步路径动态挂载

奥黛丽·逐爱者
2026-07-16 / 0 评论 / 5 阅读 / 正在检测是否收录...

FTP同步和rsync同步是两种不同的文件传输/同步机制,核心区别在于传输策略和差异检测方式:

FTP 是否每次都全部扫描?
传统 FTP 客户端/脚本:是的,通常需要全量扫描。
标准 FTP 协议本身没有"增量同步"概念
常见做法(如 lftp 的 mirror、Python ftplib 脚本)需要:
遍历远程目录列表
对比本地文件(时间戳或大小)
决定是否重新传输
这意味着每次都要读取远程完整文件列表,对大目录开销明显


指定的目录文件与日俱增,rsync没法用只能用ftp,那么有没有办法让它每个月自动换目录挂载,比如现在是7月1日自动创建并挂载7月份的目录,到了8月1日就自动创建和挂载8月份的目录。
按照这个需求可以通过 Docker 的动态挂载切换目录,目的是通过按月分目录来减少每次扫描的文件数量。
方案是修改docker-compose.yml配置指定env参数加定时脚本来实现。

services:
  vsftpd:
    image: fauria/vsftpd
    container_name: vsftpd
    restart: unless-stopped
    #network_mode: host
    ports:
      # - "20:20"
      - "2121:21"                # 控制端口
      - "65500-65509:65500-65509" # PASV 端口范围
    volumes:
      # === 统一时区卷挂载 ===
      - /etc/localtime:/etc/localtime:ro
      - /usr/share/zoneinfo:/usr/share/zoneinfo:ro
      # === 数据存储挂载 ===
      - /data/vdb/docker/compose/vsftpd/logs/vsftpd.log:/var/log/vsftpd.log   #日志
      #- /data/vdb/docker/compose/web/nginx/html/zssjapi/uploads/files:/home/vsftpd/xj_zssj_sync/zssj
      # === 动态挂载 ===
      - ${CURRENT_MONTH_DIR}:/home/vsftpd/xj_zssj_sync/${CURRENT_YEAR}/${CURRENT_MONTH}:rw
    environment:
      TZ: Asia/Shanghai
      FTP_USER: ${FTP_USER}
      FTP_PASS: ${FTP_PASS}
#      PASV_ADDRESS: 10.28.4.172  # 宿主机IP
      PASV_ADDRESS: 10.10.11.11  # 宿主机能访问到的
      PASV_MIN_PORT: 65500
      PASV_MAX_PORT: 65509
      USER_ID: 1000
      GROUP_ID: 1000

#!/bin/bash
# /opt/1panel/docker/compose/vsftpd/scripts/ftp-monthly-rotate.sh

set -e

# 配置
COMPOSE_DIR="/opt/1panel/docker/compose/vsftpd"
ENV_FILE="${COMPOSE_DIR}/.env"
FTP_USER="xj_zssj_sync"
FTP_PASS="Xj@zssj123"
BASE_DIR="/data/vdb/docker/compose/web/nginx/html/zssjapi/uploads/files"

# 获取当前小时和分钟(测试用)
# CURRENT_HOUR=$(date +%H)
# CURRENT_MINUTE=$(date +%M)
# CURRENT_MONTH_DIR="${BASE_DIR}/test_${CURRENT_HOUR}/test_${CURRENT_MINUTE}"

# 获取当前年月(月份不带前导零)用于生产
CURRENT_YEAR=$(date +%Y)
CURRENT_MONTH=$(date +%-m | sed 's/^0//')
CURRENT_MONTH_DIR="${BASE_DIR}/${CURRENT_YEAR}/${CURRENT_MONTH}"

# 创建新目录
mkdir -p "${CURRENT_MONTH_DIR}"
chmod 755 "${CURRENT_MONTH_DIR}"
# 创建测试文件
# echo "Created at: $(date '+%Y-%m-%d %H:%M:%S')" > "${CURRENT_MONTH_DIR}/test_${TIMESTAMP}.txt"
# echo "Directory: ${CURRENT_MONTH_DIR}" >> "${CURRENT_MONTH_DIR}/test_${TIMESTAMP}.txt"

# 更新 .env 文件
cat > ${ENV_FILE} << EOF
FTP_USER=${FTP_USER}
FTP_PASS=${FTP_PASS}
CURRENT_YEAR=${CURRENT_YEAR}
CURRENT_MONTH=${CURRENT_MONTH}
CURRENT_MONTH_DIR=${CURRENT_MONTH_DIR}
EOF

# 重启服务
cd ${COMPOSE_DIR}
docker-compose down
docker-compose up -d


echo "$(date '+%Y-%m-%d %H:%M:%S'): FTP 已切换至 ${CURRENT_MONTH_DIR}" >> /data/vdb/docker/compose/vsftpd/logs/ftp-rotate.log

# 1. 备份原配置
cp /opt/1panel/docker/compose/vsftpd/docker-compose.yml /opt/1panel/docker/compose/vsftpd/docker-compose.yml.bak

# 2. 修改 docker-compose.yml(按上面内容修改)

# 3. 创建脚本目录和文件
mkdir -p /opt/1panel/docker/compose/vsftpd/scripts
vi /opt/1panel/docker/compose/vsftpd/scripts/ftp-monthly-rotate.sh
# 粘贴上面脚本内容

# 4. 赋予执行权限
chmod +x /opt/1panel/docker/compose/vsftpd/scripts/ftp-monthly-rotate.sh

# 5. 执行测试
/opt/1panel/docker/compose/vsftpd/scripts/ftp-monthly-rotate.sh

# 6. 验证
docker compose ps
docker inspect vsftpd | grep -A 5 "Mounts"
cat /opt/1panel/docker/compose/vsftpd/.env

crontab -e
# 添加
0 * * * * /opt/1panel/docker/compose/vsftpd/scripts/ftp-monthly-rotate.sh
# 稳定跑后改成每月
  
# 修改定时任务为每月执行
crontab -e
# 改为
0 2 1 * * /opt/1panel/docker/compose/vsftpd/scripts/ftp-monthly-rotate.sh

# 编辑脚本,注释掉测试部分,恢复年月部分
vi /opt/1panel/docker/compose/vsftpd/scripts/ftp-monthly-rotate.sh

# 获取当前年月(月份不带前导零)
CURRENT_YEAR=$(date +%Y)
CURRENT_MONTH=$(date +%-m | sed 's/^0//')
CURRENT_MONTH_DIR="${BASE_DIR}/${CURRENT_YEAR}/${CURRENT_MONTH}"

# 注释掉小时分钟
# CURRENT_HOUR=$(date +%H)
# CURRENT_MINUTE=$(date +%M)
# CURRENT_MONTH_DIR="${BASE_DIR}/test_${CURRENT_HOUR}${CURRENT_MINUTE}"

不同机器只需要修改这两处:

volumes:
  # === 动态挂载(由.env控制) ===
  - ${CURRENT_MONTH_DIR}:/home/vsftpd/xj_tzsj_sync/tzsj:rw

environment:
  FTP_USER: ${FTP_USER}
  FTP_PASS: ${FTP_PASS}

其它都在 .env 里动态变化
脚本每次执行会重新生成 .env:

cat > ${ENV_FILE} << EOF
FTP_USER=${FTP_USER}
FTP_PASS=${FTP_PASS}
CURRENT_HOUR=${CURRENT_HOUR}
CURRENT_MINUTE=${CURRENT_MINUTE}
CURRENT_MONTH_DIR=${CURRENT_MONTH_DIR}
EOF

# 获取时间戳(用于文件名)
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')

# 创建新目录
mkdir -p "${CURRENT_MONTH_DIR}"
chmod 755 "${CURRENT_MONTH_DIR}"

# 创建测试文件
echo "Created at: $(date '+%Y-%m-%d %H:%M:%S')" > "${CURRENT_MONTH_DIR}/test_${TIMESTAMP}.txt"
echo "Directory: ${CURRENT_MONTH_DIR}" >> "${CURRENT_MONTH_DIR}/test_${TIMESTAMP}.txt"

执行后,目录里会有这样的文件:

/data/.../uploads/files/test_1430/
└── test_20260716_143000.txt

0

评论 (0)

取消