From 08e8f067ad05d3759f3f8289061c247d7aeb43be Mon Sep 17 00:00:00 2001 From: Seth Date: Sun, 15 Mar 2026 23:40:41 -0400 Subject: [PATCH] Paper fork: harden latest.log tailing across rotation/restart - Detect inode changes and truncation in tail_log - Reopen latest.log automatically when Paper recreates log file - Prevent lost trigger parsing after server restarts --- mc_aigod_paper.py | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/mc_aigod_paper.py b/mc_aigod_paper.py index ae049b8..9fdaad8 100644 --- a/mc_aigod_paper.py +++ b/mc_aigod_paper.py @@ -6,7 +6,7 @@ validates targets, and executes commands via RCON. Config: /etc/mc_aigod.json """ -import json, random, re, socket, struct, threading, time, logging +import json, os, random, re, socket, struct, threading, time, logging from collections import deque from datetime import datetime import requests @@ -1534,14 +1534,34 @@ def divine_intervention_loop(config): # --------------------------------------------------------------------------- def tail_log(log_path): - with open(log_path, 'r') as f: - f.seek(0, 2) - while True: - line = f.readline() - if line: - yield line - else: - time.sleep(0.2) + """ + Follow latest.log robustly across truncation/rotation. + Paper can recreate latest.log on restart; we detect inode changes and reopen. + """ + f = open(log_path, 'r') + f.seek(0, 2) + current_inode = os.fstat(f.fileno()).st_ino + + while True: + line = f.readline() + if line: + yield line + continue + + # No new line yet; check for rotation/truncation + try: + st = os.stat(log_path) + if st.st_ino != current_inode or st.st_size < f.tell(): + f.close() + f = open(log_path, 'r') + current_inode = os.fstat(f.fileno()).st_ino + f.seek(0, 2) + log.info("Reattached log tail after latest.log rotation/truncation") + except FileNotFoundError: + # During restart, file may not exist briefly + pass + + time.sleep(0.2) # --------------------------------------------------------------------------- # Main