refet tot per a docker
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
savefiles_logger:
|
||||
image: python:3.11-slim
|
||||
container_name: savefiles_logger
|
||||
working_dir: /app
|
||||
command: ["python3", "watcher.py"]
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
# Código
|
||||
- /home/sergio/gitea/savefiles_logger:/app
|
||||
|
||||
# Datos persistentes (backups + logs)
|
||||
- savefiles_data:/app/data
|
||||
|
||||
# Carpeta de saves del host
|
||||
- /sustancia/home/saves:/saves
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "python3", "-c", "import os; exit(0 if os.path.exists('/app/watcher.py') else 1)"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
volumes:
|
||||
savefiles_data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: /var/volumes/savefiles_logger
|
||||
@@ -1,4 +1,4 @@
|
||||
FILES = [
|
||||
"/sustancia/home/saves/Beetle PSX HW/Suikoden II (USA) (Bug Fix) (Pyriel) (2.02.078).1.mcr",
|
||||
"/sustancia/home/saves/Beetle PSX HW/Suikoden II (USA) (Bug Fix) (Pyriel) (2.02.078).srm",
|
||||
"/saves/Beetle PSX HW/Suikoden II (USA) (Bug Fix) (Pyriel) (2.02.078).1.mcr",
|
||||
"/saves/Beetle PSX HW/Suikoden II (USA) (Bug Fix) (Pyriel) (2.02.078).srm",
|
||||
]
|
||||
|
||||
+45
-11
@@ -2,11 +2,40 @@ import os
|
||||
import time
|
||||
import shutil
|
||||
import hashlib
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from files import FILES
|
||||
|
||||
CHECK_INTERVAL = 60 # segundos
|
||||
|
||||
# Rutas base (dentro del contenedor)
|
||||
DATA_DIR = "data"
|
||||
BACKUPS_ROOT = os.path.join(DATA_DIR, "backups")
|
||||
LOGS_DIR = os.path.join(DATA_DIR, "logs")
|
||||
|
||||
os.makedirs(BACKUPS_ROOT, exist_ok=True)
|
||||
os.makedirs(LOGS_DIR, exist_ok=True)
|
||||
|
||||
# Configuración de logging
|
||||
LOG_FILE = os.path.join(LOGS_DIR, "watcher.log")
|
||||
logging.basicConfig(
|
||||
filename=LOG_FILE,
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s [%(levelname)s] %(message)s"
|
||||
)
|
||||
|
||||
def log_info(msg):
|
||||
print(msg)
|
||||
logging.info(msg)
|
||||
|
||||
def log_warn(msg):
|
||||
print(msg)
|
||||
logging.warning(msg)
|
||||
|
||||
def log_error(msg):
|
||||
print(msg)
|
||||
logging.error(msg)
|
||||
|
||||
def sha256sum(path):
|
||||
"""Devuelve el hash SHA256 del fichero."""
|
||||
h = hashlib.sha256()
|
||||
@@ -16,10 +45,10 @@ def sha256sum(path):
|
||||
return h.hexdigest()
|
||||
|
||||
def ensure_backup_dir(file_path):
|
||||
"""Crea backup/<nombre_sin_ext>/ si no existe."""
|
||||
"""Crea data/backups/<nombre_sin_ext>/ si no existe."""
|
||||
file_name = os.path.basename(file_path)
|
||||
name, _ = os.path.splitext(file_name)
|
||||
backup_dir = os.path.join("backup", name)
|
||||
backup_dir = os.path.join(BACKUPS_ROOT, name)
|
||||
os.makedirs(backup_dir, exist_ok=True)
|
||||
return backup_dir
|
||||
|
||||
@@ -39,33 +68,38 @@ def backup_file(file_path):
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
dest = os.path.join(backup_dir, f"{name}_{timestamp}{ext}")
|
||||
shutil.copy2(file_path, dest)
|
||||
print(f"[BACKUP] Copia creada: {dest}")
|
||||
log_info(f"[BACKUP] Copia creada: {dest}")
|
||||
|
||||
def process_file(file_path):
|
||||
"""Comprueba si hay cambios y crea backup si es necesario."""
|
||||
if not os.path.isfile(file_path):
|
||||
print(f"[WARN] No existe: {file_path}")
|
||||
log_warn(f"[WARN] No existe: {file_path}")
|
||||
return
|
||||
|
||||
latest = get_latest_backup(file_path)
|
||||
|
||||
if latest is None:
|
||||
print(f"[INIT] No hay copia previa de {file_path}, creando primera copia...")
|
||||
log_info(f"[INIT] No hay copia previa de {file_path}, creando primera copia...")
|
||||
backup_file(file_path)
|
||||
return
|
||||
|
||||
# Comparamos hashes
|
||||
current_hash = sha256sum(file_path)
|
||||
latest_hash = sha256sum(latest)
|
||||
try:
|
||||
current_hash = sha256sum(file_path)
|
||||
latest_hash = sha256sum(latest)
|
||||
except Exception as e:
|
||||
log_error(f"[ERROR] Calculando hash: {e}")
|
||||
return
|
||||
|
||||
if current_hash != latest_hash:
|
||||
print(f"[CHANGE] Detectado cambio en {file_path}, creando nueva copia...")
|
||||
log_info(f"[CHANGE] Detectado cambio en {file_path}, creando nueva copia...")
|
||||
backup_file(file_path)
|
||||
else:
|
||||
print(f"[OK] Sin cambios en {file_path}")
|
||||
log_info(f"[OK] Sin cambios en {file_path}")
|
||||
|
||||
def main():
|
||||
print("Iniciando watcher de saves...")
|
||||
log_info("Iniciando watcher de saves...")
|
||||
log_info(f"Backups en: {os.path.abspath(BACKUPS_ROOT)}")
|
||||
log_info(f"Logs en: {os.path.abspath(LOGS_DIR)}")
|
||||
|
||||
while True:
|
||||
for f in FILES:
|
||||
|
||||
Reference in New Issue
Block a user