# <<*>> -^v- SNOWARE APPLICATION # usage: MINESENTINEL mainloop. # author: S.A. # time: 2026-06-07 # Copyright (c) [2026] [S.A. SNOWARE-SCU] # [MineSentinel] is licensed under Mulan PubL v2. # You can use this software according to the terms and conditions of the Mulan PubL v2. # You may obtain a copy of Mulan PubL v2 at: # http://license.coscl.org.cn/MulanPubL-2.0 # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. # See the Mulan PubL v2 for more details. # main.rb 顶部添加 begin # 原有代码 rescue => e # 强制输出到stderr $stderr.puts "[CRITICAL] Unhandled exception: #{e.message}" $stderr.puts e.backtrace.join("\n") exit 1 end puts ' ___ __ ___ ___ ___ ' puts ' |\/| | |\ | |__ /__` |__ |\ | | | |\ | |__ | ' puts ' | | | | \| |___ .__/ |___ | \| | | | \| |___ |___ ' puts " MineSentinel dev-rolling version by <*> S.A. [@SNOWARE] and owned by SCU team." puts " E-mail: SALflake@qq.com | QQ: 758522192 | Website: https://https://swe-iss.rth1.xyz/softwares/minesentinel." puts " Copyleft (c) 2026 S.A. SNOWARE-SCU. This program is licensed under Mulan PubL v2." puts require_relative 'method_executor' # 日志系统在此时初始化 MethodExecutor.record("debug", "init", "Initialized MethodExecutor, which implements logging system and intervening functions.") require_relative 'server_status_detector' require_relative 'systemd_notifier' # 心跳系统在此时初始化 MethodExecutor.record("debug", "init", "Initialized SystemdNotifier, which implements systemd watchdog feeder.") # 确认是否具有展开干预操作的权限 如果因场景不同不需要请注释这部分内容 unless Process.euid == 0 MethodExecutor.record("error", "init", "Permission denied: root required to intervene Systemd Services.") raise Errno::EPERM end MethodExecutor.record("info", "mainloop", "MineSentinel started, entering mainloop.") # 初次启动:MineSentinel 先于 minecraft 启动(systemd Before=), # 等待服务器端口就绪,避免误判为崩溃 INITIAL_GRACE = 300 # 初次启动等待 300 秒 MethodExecutor.record("info", "mainloop", "Initial startup grace period #{INITIAL_GRACE}s — waiting for server to come up...") grace_deadline = Time.now + INITIAL_GRACE while Time.now < grace_deadline sleep 5 if ServerStatusDetector::MinecraftServer.self_diag[:type] MethodExecutor.record("info", "mainloop", "Server port is open during grace period, resuming normal monitoring.") break end end MethodExecutor.record("info", "mainloop", "Grace period ended.") # Functional mainloop. def main chkrslt = ServerStatusDetector::MinecraftServer.self_diag if chkrslt[:type] MethodExecutor.record("debug", "mainloop", "Server health check passed.") else MethodExecutor.record("warn", "mainloop", "Server health check FAILED: #{chkrslt[:message]}") for operation in chkrslt[:operation] if operation == "Record" # 消息已在 self_diag 中生成,这里仅记录操作 MethodExecutor.record("warn", "mainloop", "Action: Record -> Server died!") elsif operation == "ForceResetServerProcess" MethodExecutor.record("info", "mainloop", "Action: ForceResetServerProcess triggered.") MethodExecutor.reset_minecraft_server # 重启后等待服务器启动(MC服务器启动通常需要30秒~2分钟) cooldown_duration = 200 # 200秒冷却期 cooldown_beg = Time.now MethodExecutor.record("info", "mainloop", "Cooling down #{cooldown}s for server startup...") while Time.now < cooldown_beg + cooldown_duration sleep 1 SystemdNotifier.notify("WATCHDOG=1") end MethodExecutor.record("info", "mainloop", "Cooldown finished, resuming monitoring.") end end end end while true sleep 1.5 SystemdNotifier.notify("WATCHDOG=1") main end