eliminat log persistent
This commit is contained in:
+8
-11
@@ -1,34 +1,31 @@
|
|||||||
version: "3.9"
|
version: "3.9"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
savefiles_logger:
|
gamewatcher:
|
||||||
image: python:3.11-slim
|
image: python:3.11-slim
|
||||||
container_name: savefiles_logger
|
container_name: gamewatcher
|
||||||
working_dir: /app
|
working_dir: /data/app
|
||||||
command: ["python3", "watcher.py"]
|
command: ["python3", "watcher.py"]
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
# Código
|
# Volumen persistente con scripts y backups
|
||||||
- /home/sergio/gitea/savefiles_logger:/app
|
- gamewatcher_data:/data
|
||||||
|
|
||||||
# Datos persistentes (backups + logs)
|
|
||||||
- savefiles_data:/app/data
|
|
||||||
|
|
||||||
# Carpeta de saves del host
|
# Carpeta de saves del host
|
||||||
- /sustancia/home/saves:/saves
|
- /sustancia/home/saves:/saves
|
||||||
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "python3", "-c", "import os; exit(0 if os.path.exists('/app/watcher.py') else 1)"]
|
test: ["CMD", "python3", "-c", "import os; exit(0 if os.path.exists('/data/app/watcher.py') else 1)"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 10s
|
start_period: 10s
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
savefiles_data:
|
gamewatcher_data:
|
||||||
driver: local
|
driver: local
|
||||||
driver_opts:
|
driver_opts:
|
||||||
type: none
|
type: none
|
||||||
o: bind
|
o: bind
|
||||||
device: /var/volumes/savefiles_logger
|
device: /var/volumes/gamewatcher
|
||||||
|
|||||||
+15
-39
@@ -2,42 +2,23 @@ import os
|
|||||||
import time
|
import time
|
||||||
import shutil
|
import shutil
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from files import FILES
|
from files import FILES
|
||||||
|
|
||||||
CHECK_INTERVAL = 60 # segundos
|
CHECK_INTERVAL = 300 # 5 minutos
|
||||||
|
|
||||||
# Rutas base (dentro del contenedor)
|
# Rutas dentro del contenedor
|
||||||
DATA_DIR = "data"
|
DATA_DIR = "/data"
|
||||||
|
APP_DIR = os.path.join(DATA_DIR, "app")
|
||||||
BACKUPS_ROOT = os.path.join(DATA_DIR, "backups")
|
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(BACKUPS_ROOT, exist_ok=True)
|
||||||
os.makedirs(LOGS_DIR, exist_ok=True)
|
|
||||||
|
|
||||||
# Configuración de logging
|
def log(msg):
|
||||||
LOG_FILE = os.path.join(LOGS_DIR, "watcher.log")
|
ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
logging.basicConfig(
|
print(f"[{ts}] {msg}", flush=True)
|
||||||
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):
|
def sha256sum(path):
|
||||||
"""Devuelve el hash SHA256 del fichero."""
|
|
||||||
h = hashlib.sha256()
|
h = hashlib.sha256()
|
||||||
with open(path, "rb") as f:
|
with open(path, "rb") as f:
|
||||||
for chunk in iter(lambda: f.read(4096), b""):
|
for chunk in iter(lambda: f.read(4096), b""):
|
||||||
@@ -45,7 +26,6 @@ def sha256sum(path):
|
|||||||
return h.hexdigest()
|
return h.hexdigest()
|
||||||
|
|
||||||
def ensure_backup_dir(file_path):
|
def ensure_backup_dir(file_path):
|
||||||
"""Crea data/backups/<nombre_sin_ext>/ si no existe."""
|
|
||||||
file_name = os.path.basename(file_path)
|
file_name = os.path.basename(file_path)
|
||||||
name, _ = os.path.splitext(file_name)
|
name, _ = os.path.splitext(file_name)
|
||||||
backup_dir = os.path.join(BACKUPS_ROOT, name)
|
backup_dir = os.path.join(BACKUPS_ROOT, name)
|
||||||
@@ -53,7 +33,6 @@ def ensure_backup_dir(file_path):
|
|||||||
return backup_dir
|
return backup_dir
|
||||||
|
|
||||||
def get_latest_backup(file_path):
|
def get_latest_backup(file_path):
|
||||||
"""Devuelve la ruta del backup más reciente o None si no hay."""
|
|
||||||
backup_dir = ensure_backup_dir(file_path)
|
backup_dir = ensure_backup_dir(file_path)
|
||||||
files = sorted(os.listdir(backup_dir), reverse=True)
|
files = sorted(os.listdir(backup_dir), reverse=True)
|
||||||
if not files:
|
if not files:
|
||||||
@@ -61,25 +40,23 @@ def get_latest_backup(file_path):
|
|||||||
return os.path.join(backup_dir, files[0])
|
return os.path.join(backup_dir, files[0])
|
||||||
|
|
||||||
def backup_file(file_path):
|
def backup_file(file_path):
|
||||||
"""Crea una copia con timestamp."""
|
|
||||||
backup_dir = ensure_backup_dir(file_path)
|
backup_dir = ensure_backup_dir(file_path)
|
||||||
file_name = os.path.basename(file_path)
|
file_name = os.path.basename(file_path)
|
||||||
name, ext = os.path.splitext(file_name)
|
name, ext = os.path.splitext(file_name)
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
dest = os.path.join(backup_dir, f"{name}_{timestamp}{ext}")
|
dest = os.path.join(backup_dir, f"{name}_{timestamp}{ext}")
|
||||||
shutil.copy2(file_path, dest)
|
shutil.copy2(file_path, dest)
|
||||||
log_info(f"[BACKUP] Copia creada: {dest}")
|
log(f"[BACKUP] Copia creada: {dest}")
|
||||||
|
|
||||||
def process_file(file_path):
|
def process_file(file_path):
|
||||||
"""Comprueba si hay cambios y crea backup si es necesario."""
|
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
log_warn(f"[WARN] No existe: {file_path}")
|
log(f"[WARN] No existe: {file_path}")
|
||||||
return
|
return
|
||||||
|
|
||||||
latest = get_latest_backup(file_path)
|
latest = get_latest_backup(file_path)
|
||||||
|
|
||||||
if latest is None:
|
if latest is None:
|
||||||
log_info(f"[INIT] No hay copia previa de {file_path}, creando primera copia...")
|
log(f"[INIT] Primera copia de {file_path}")
|
||||||
backup_file(file_path)
|
backup_file(file_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -87,19 +64,18 @@ def process_file(file_path):
|
|||||||
current_hash = sha256sum(file_path)
|
current_hash = sha256sum(file_path)
|
||||||
latest_hash = sha256sum(latest)
|
latest_hash = sha256sum(latest)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log_error(f"[ERROR] Calculando hash: {e}")
|
log(f"[ERROR] Hash: {e}")
|
||||||
return
|
return
|
||||||
|
|
||||||
if current_hash != latest_hash:
|
if current_hash != latest_hash:
|
||||||
log_info(f"[CHANGE] Detectado cambio en {file_path}, creando nueva copia...")
|
log(f"[CHANGE] Detectado cambio en {file_path}")
|
||||||
backup_file(file_path)
|
backup_file(file_path)
|
||||||
else:
|
else:
|
||||||
log_info(f"[OK] Sin cambios en {file_path}")
|
log(f"[OK] Sin cambios en {file_path}")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
log_info("Iniciando watcher de saves...")
|
log("GameWatcher iniciado")
|
||||||
log_info(f"Backups en: {os.path.abspath(BACKUPS_ROOT)}")
|
log(f"Backups en: {BACKUPS_ROOT}")
|
||||||
log_info(f"Logs en: {os.path.abspath(LOGS_DIR)}")
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
for f in FILES:
|
for f in FILES:
|
||||||
|
|||||||
Reference in New Issue
Block a user