dev1.0 版本
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# <<*>> -^v- SNOWARE APPLICATION
|
||||
# usage: Automatic operator implementation.
|
||||
# author: S.A.
|
||||
# time: 2026-06-07
|
||||
# license: All rights received.
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
PERSISTENCE_PERIOD = 30 # Wait for systemctl to take the order.
|
||||
|
||||
require 'logger'
|
||||
require_relative 'server_status_detector'
|
||||
class MethodExecutor
|
||||
public
|
||||
RST_COUNTS_LIMIT = 10
|
||||
@@rst_counter = 0
|
||||
# Initialize the standard log system.
|
||||
@@logger = Logger.new(STDOUT) # This script will be launched as a systemd server.
|
||||
# Fetch the environmental variable and convert it into log level.
|
||||
@@logger.level = case ENV["LOG_LEVEL"] # @为单个实例(半生不熟的概念,貌似是在不同的空间独立创建),@@为共享同一个
|
||||
when nil # Default config.
|
||||
Logger::Severity::DEBUG
|
||||
when "debug"
|
||||
Logger::Severity::DEBUG
|
||||
when "info"
|
||||
Logger::Severity::INFO
|
||||
when "warn"
|
||||
Logger::Severity::WARN
|
||||
when "error"
|
||||
Logger::Severity::ERROR
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
@@logger.progname = "MineSentinel"
|
||||
|
||||
def self.record(level, module_name, message)
|
||||
case level
|
||||
when "info"
|
||||
@@logger.info("#{module_name}: #{message}")
|
||||
when "warn"
|
||||
@@logger.warn("#{module_name}: #{message}")
|
||||
when "error"
|
||||
@@logger.error("#{module_name}: #{message}")
|
||||
when "debug"
|
||||
@@logger.debug("#{module_name}: #{message}")
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
end
|
||||
|
||||
def self.reset_minecraft_server
|
||||
|
||||
self.record("info", "reset", "Attempt ##{@@rst_counter + 1} to reset Minecraft server.")
|
||||
|
||||
if @@rst_counter >= RST_COUNTS_LIMIT
|
||||
self.record("error", "reset",
|
||||
"Tried #{RST_COUNTS_LIMIT} times and failed, now I'll idle until server is manually restarted.")
|
||||
while true
|
||||
sleep 10
|
||||
if ServerStatusDetector::MinecraftServer.self_diag[:type] == true
|
||||
self.record("info", "reset", "Server recovered! Resuming normal monitoring.")
|
||||
@@rst_counter = 0
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@rst_counter += 1
|
||||
|
||||
unless Process.euid == 0
|
||||
self.record("error", "reset", "Permission denied: root required to manage systemd services.")
|
||||
raise Errno::EPERM
|
||||
end
|
||||
|
||||
self.record("info", "reset", "Spawning 'systemctl restart minecraft' (PID will be captured)...")
|
||||
pid = spawn "systemctl restart minecraft"
|
||||
self.record("debug", "reset", "systemctl restart spawned with PID #{pid}.")
|
||||
tick_beg = Time.now
|
||||
|
||||
while true
|
||||
sleep 0.5
|
||||
begin
|
||||
proc_status = Process.waitpid2(pid, Process::WNOHANG)
|
||||
if proc_status # 子进程已退出,返回 [pid, status]
|
||||
_, status = proc_status
|
||||
elapsed = (Time.now - tick_beg).round(2)
|
||||
if status.success?
|
||||
self.record("info", "reset", "'systemctl restart' succeeded in #{elapsed}s.")
|
||||
@@rst_counter = 0 # 成功时重置计数器
|
||||
break
|
||||
else
|
||||
self.record("error", "reset", "'systemctl restart' failed with exitcode #{status.exitstatus} after #{elapsed}s.")
|
||||
break
|
||||
end
|
||||
else # 子进程仍在运行 (WNOHANG 返回 nil)
|
||||
if Time.now - tick_beg > PERSISTENCE_PERIOD then
|
||||
self.record("warn", "reset",
|
||||
"'systemctl restart' timed out after #{PERSISTENCE_PERIOD}s. Force-killing PID #{pid}...")
|
||||
system "kill -9 #{pid}"
|
||||
self.record("warn", "reset", "Running 'systemctl kill minecraft' (last resort)...")
|
||||
system "systemctl kill minecraft" # 没招了,毁灭吧
|
||||
sleep 0.5
|
||||
self.record("info", "reset", "Running 'systemctl start minecraft' (rebirth)...")
|
||||
system "systemctl start minecraft" # 重生
|
||||
self.record("info", "reset", "Force-reset sequence completed.")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user