import os import sys import subprocess import yaml import shutil # Constants SCRIPTS_DIR = "/scripts" DEFAULTS_DIR = "/app/defaults" CONFIG_PATH = os.path.join(SCRIPTS_DIR, "config.yaml") CRONTAB_PATH = "/app/generated_crontab" def initialize_volume_if_empty(): """Copies default files to /scripts if config.yaml is missing.""" if not os.path.exists(CONFIG_PATH): print("---------------------------------") print("No config found in volume. Initializing with defaults...") # Ensure directory exists os.makedirs(SCRIPTS_DIR, exist_ok=True) # Copy all files from defaults to scripts if os.path.exists(DEFAULTS_DIR): for filename in os.listdir(DEFAULTS_DIR): src = os.path.join(DEFAULTS_DIR, filename) dst = os.path.join(SCRIPTS_DIR, filename) if os.path.isfile(src): shutil.copy2(src, dst) print(f" -> Created: {filename}") print("Initialization complete.") print("---------------------------------") else: print(f"Found existing config at {CONFIG_PATH}. Using it.") def install_dependencies(deps): if not deps: return print(f"Installing {len(deps)} dependencies...") subprocess.check_call([sys.executable, "-m", "pip", "install", "--no-cache-dir"] + deps) def generate_crontab(jobs): print(f"Scheduling {len(jobs)} jobs...") lines = [] for job in jobs: schedule = job['schedule'] script = job['script'] # Use -u for unbuffered output command = f"python3 -u {SCRIPTS_DIR}/{script}" lines.append(f"{schedule} {command}") print(f" -> Loaded: {script} [{schedule}]") with open(CRONTAB_PATH, "w") as f: f.write("\n".join(lines) + "\n") def main(): # 1. Initialize Volume (The new feature) initialize_volume_if_empty() # 2. Read Config if not os.path.exists(CONFIG_PATH): print(f"Error: {CONFIG_PATH} still not found after initialization.") sys.exit(1) with open(CONFIG_PATH, "r") as f: config = yaml.safe_load(f) # 3. Setup Environment install_dependencies(config.get("dependencies", [])) generate_crontab(config.get("jobs", [])) # 4. Start Supercronic print("Starting Scheduler...") print("--------------------------------------------") sys.stdout.flush() # Wir starten Supercronic und leiten stderr (wo Logs sind) an stdout weiter # und pipen das Ganze in unseren log_formatter.py cmd = f"supercronic {CRONTAB_PATH} 2>&1 | python3 -u /app/log_formatter.py" # shell=True ist hier notwendig für die Pipe "|" subprocess.call(cmd, shell=True) if __name__ == "__main__": main()