tidy the file tree
This commit is contained in:
+124
@@ -0,0 +1,124 @@
|
||||
# <<*>> -^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.
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
||||
def main
|
||||
puts ' ___ __ ___ ___ ___ '
|
||||
puts ' |\/| | |\ | |__ /__` |__ |\ | | | |\ | |__ | '
|
||||
puts ' | | | | \| |___ .__/ |___ | \| | | | \| |___ |___ '
|
||||
puts ' MineSentinel dev-rolling version by <*> S.A. [@SNOWARE] and owned by SCU team.'
|
||||
puts ' Copyleft (c) 2026 S.A. SNOWARE-SCU. This program is licensed under Mulan PubL v2.'
|
||||
puts ' E-mail: SALflake@qq.com | QQ: 758522192 | Website: https://swe-iss.rth1.xyz/softwares/minesentinel.'
|
||||
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' # 心跳系统在此时初始化
|
||||
require_relative 'config'
|
||||
MethodExecutor.record('debug', 'init', 'Initialized SystemdNotifier, which implements systemd watchdog feeder.')
|
||||
|
||||
# 确认是否具有展开干预操作的权限 如果因场景不同不需要请注释这部分内容
|
||||
unless Process.euid.zero?
|
||||
MethodExecutor.record('error', 'init', 'Permission denied: root required to intervene Systemd Services.')
|
||||
raise Errno::EPERM
|
||||
end
|
||||
|
||||
MethodExecutor.record('info', 'mainloop', 'MineSentinel started, entering mainloop.')
|
||||
|
||||
require_relative 'updates'
|
||||
|
||||
begin
|
||||
upd_result = UpdateManager.check
|
||||
if upd_result[:status] == :NewerAvailable
|
||||
MethodExecutor.record('info', 'updates',
|
||||
"Update #{upd_result[:version]} available, please check the git repo for details.")
|
||||
end
|
||||
rescue StandardError => e
|
||||
MethodExecutor.record('error', 'updates', e.to_s)
|
||||
end
|
||||
|
||||
# 初次启动:MineSentinel 先于 minecraft 启动(systemd Before=),
|
||||
# 等待服务器端口就绪,避免误判为崩溃
|
||||
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
|
||||
next unless ServerStatusDetector::MinecraftServer.self_diag[:type]
|
||||
|
||||
MethodExecutor.record('info', 'mainloop',
|
||||
'Server port is open during grace period, resuming normal monitoring.')
|
||||
break
|
||||
end
|
||||
MethodExecutor.record('info', 'mainloop', 'Grace period ended.')
|
||||
main_loop
|
||||
end
|
||||
|
||||
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
||||
# Functional mainloop.
|
||||
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
||||
def main_once
|
||||
chkrslts = []
|
||||
(0..TRY_TIMES).each do
|
||||
chkrslt = ServerStatusDetector::MinecraftServer.self_diag
|
||||
chkrslts.append(chkrslt)
|
||||
end
|
||||
if chkrslts.all? { |chkrslt_in| chkrslt_in[:type] }
|
||||
MethodExecutor.record('debug', 'mainloop', 'Server health check passed.')
|
||||
else
|
||||
chkrslts.each do |result|
|
||||
MethodExecutor.record('warn', 'mainloop', "Server health check FAILED: #{result[:message]}")
|
||||
end
|
||||
MethodExecutor.record('info', 'mainloop', "Checked #{TRY_TIMES} time.")
|
||||
if chkrslts.any? { |chkrslt_in| chkrslt_in[:operation].include?('Record') }
|
||||
MethodExecutor.record('warn', 'mainloop', 'Action: Record -> Server died!')
|
||||
if chkrslts.any? { |chkrslt_in| chkrslt_in[:message] == 'Server died for unknown reason, and will be restarted.' }
|
||||
MethodExecutor.record('info', 'mainloop', 'Action: ForceResetServerProcess triggered.')
|
||||
MethodExecutor.reset_minecraft_server
|
||||
# 重启后等待服务器启动(MC服务器启动通常需要30秒~2分钟)
|
||||
cooldown_beg = Time.now
|
||||
MethodExecutor.record('info', 'mainloop', "Cooling down #{RST_COOLDOWN_DURATION}s for server startup...")
|
||||
# rubocop:disable Metrics/BlockNesting
|
||||
while Time.now < cooldown_beg + RST_COOLDOWN_DURATION
|
||||
sleep 1
|
||||
SystemdNotifier.notify('WATCHDOG=1')
|
||||
end
|
||||
# rubocop:enable Metrics/BlockNesting
|
||||
MethodExecutor.record('info', 'mainloop', 'Cooldown finished, resuming monitoring.')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
||||
def main_loop
|
||||
loop do
|
||||
sleep CHECK_INTERVAL
|
||||
SystemdNotifier.notify('WATCHDOG=1')
|
||||
main_once
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
main
|
||||
rescue StandardError => e
|
||||
# 强制输出到stderr
|
||||
warn "[CRITICAL] Unhandled exception: #{e.message}"
|
||||
warn e.backtrace&.join("\n")
|
||||
exit 1
|
||||
end
|
||||
Reference in New Issue
Block a user