Утилита/сервис для надёжного перемещения файлов из одной директории в другую. Основной сценарий — забирать файлы из общей (например, NFS) папки, проверять их целостность и перекладывать в целевую директорию, ведя JSON‑манифест обработанных файлов.
- Источник: директория
SOURCE_DIR. - Назначение: директория
TARGET_DIR. - Для каждого файла в
SOURCE_DIR(кроме триггер‑файла) сервис:- ждёт, пока файл «стабилизируется» по размеру (не меняется в течение
STABLE_SECONDS); - считает SHA256‑хеш и собирает метаданные (имя, размер, время изменения);
- добавляет запись в JSON‑манифест (
MANIFEST_PREFIX-<timestamp>.jsonвSOURCE_DIR); - копирует файл в
TARGET_DIR, ещё раз сверяя SHA256; - удаляет исходный файл из
SOURCE_DIR.
- ждёт, пока файл «стабилизируется» по размеру (не меняется в течение
Есть два режима работы, задаются через RUN_MODE:
trigger(по умолчанию) — сервис крутится в бесконечном цикле и реагирует на появление триггер‑файла (см. ниже).cron— однократный проход: собрать манифест и переместить файлы, затем выйти (удобно для запуска черезcronили KubernetesCronJob).
В режиме trigger сервис:
- Постоянно проверяет наличие файла
TRIGGER_FILEвSOURCE_DIR(по умолчаниюtrigger.txt). - Когда файл появляется и становится стабильным по размеру, запускается обработка: создание манифеста и перенос всех файлов.
- После успешной обработки триггер‑файл удаляется.
Таким образом, внешняя система может просто создать триггер‑файл в общей папке, чтобы запустить перемещение накопившихся данных.
Обязательные:
SOURCE_DIR— директория‑источник файлов.TARGET_DIR— целевая директория, куда будут перемещаться файлы.
Необязательные (есть значения по умолчанию):
STABLE_SECONDS— сколько секунд размер файла должен оставаться неизменным, чтобы считать его «стабильным» (по умолчанию3).POLL_INTERVAL— интервал в секундах между проверками файлов и триггера (по умолчанию1).TRIGGER_FILE— имя триггер‑файла (по умолчаниюtrigger.txt).RETRY_COUNT— количество попыток чтения/копирования файла при ошибках (по умолчанию3).RETRY_DELAY— пауза в секундах между попытками (по умолчанию2).MANIFEST_PREFIX— префикс имени JSON‑манифеста (по умолчаниюmanifest).RUN_MODE— режим работы:triggerилиcron(по умолчаниюtrigger).LOG_LEVEL— уровень логирования (INFO,DEBUG, …; по умолчаниюINFO).LOG_FILE— путь до файла логов; если не задан, лог пишется в stdout/stderr.
Требуется Python 3.12+.
Простейший пример однократного запуска (режим cron):
export SOURCE_DIR=/path/to/source
export TARGET_DIR=/path/to/target
export RUN_MODE=cron
python main.pyРежим ожидания триггера:
export SOURCE_DIR=/path/to/source
export TARGET_DIR=/path/to/target
export RUN_MODE=trigger
python main.pyСборка образа:
docker build -t file-mover .Запуск контейнера с примонтированным общим каталогом:
docker run --rm \
-e SOURCE_DIR=/data/in \
-e TARGET_DIR=/data/out \
-e RUN_MODE=trigger \
-v /host/data:/data \
file-moverВ манифестах и логах SOURCE_DIR и TARGET_DIR относятся к файловой системе
контейнера, поэтому обычно используется общий том/каталог, примонтированный
как в контейнер, так и на стороне других сервисов.
В каталоге k8s/ есть готовые манифесты:
deployment.yaml— обычныйDeploymentдля постоянной работы в режимеtrigger.nfs-file-mover-cron.yaml—CronJob, который запускает контейнер раз в день (или по расписанию) в режимеcron.
Оба манифеста рассчитаны на работу с NFS‑шарой:
- NFS‑том монтируется в директорию
/development/Light_Data. SOURCE_DIRиTARGET_DIRуказывают на подпапки внутри этого тома.
Перед применением манифестов под свои нужды обычно нужно:
- поправить
serverиpathв описании NFS‑тома; - при необходимости изменить
scheduleуCronJob; - обновить образ контейнера (
image: ...).
- Язык: Python 3.12 (стандартная библиотека:
os,time,hashlib,json,loggingи др.). - Управление зависимостями:
uv, конфигурация вpyproject.toml/uv.lock. - Качество кода / dev‑инструменты:
ruff— линтер и форматтер;mypy— статическая типизация;prekи.pre-commit-config.yaml— хуки pre‑commit.
- Контейнеризация:
Docker, многоступенчатый образ на базеpython:3.12-slim-bookworm. - Оркестрация:
Kubernetes(Deployment,CronJob). - Хранилище: сетевой NFS‑том (см. манифесты в
k8s/), примонтированный в контейнер.