2026-06-07 19:35:17 +08:00
<!DOCTYPE html>
<!--
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.
品牌标识(Logo / SVG / 项目名称" MineSentinel")保留所有权利,未经许可不得用于衍生项目。
-->
< html lang = "zh-CN" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > MineSentinel — Minecraft 服务器守护进程< / title >
< script src = 'https://gitee.com/SCU_team/mine-sentinel/widget_preview' async defer > < / script >
< style >
: root {
--amber : #f59e0b ;
--orange : #ea580c ;
--coral : #e8613c ;
--warm-bg : #ffedd5 ;
--card-bg : #fff7ed ;
--text : #431407 ;
--text-dim : #7c2d12 ;
}
* { margin : 0 ; padding : 0 ; box-sizing : border-box ; }
body {
font-family : - apple-system , BlinkMacSystemFont , 'Segoe UI' , Roboto , sans-serif ;
line-height : 1.7 ;
color : var ( - - text ) ;
background : linear-gradient ( 160 deg , #f97316 0 % , #ea580c 40 % , #dc2626 100 % ) ;
min-height : 100 vh ;
position : relative ;
overflow-x : hidden ;
}
/* Geometric background elements */
body :: before {
content : '' ;
position : fixed ;
top : -50 % ;
left : -50 % ;
width : 200 % ;
height : 200 % ;
background :
repeating-linear-gradient ( 30 deg , transparent , transparent 80 px , rgba ( 255 , 255 , 255 , 0.03 ) 80 px , rgba ( 255 , 255 , 255 , 0.03 ) 82 px ) ,
repeating-linear-gradient ( -60 deg , transparent , transparent 120 px , rgba ( 255 , 255 , 255 , 0.04 ) 120 px , rgba ( 255 , 255 , 255 , 0.04 ) 122 px ) ;
pointer-events : none ;
z-index : 0 ;
}
. geo-hex {
position : fixed ;
pointer-events : none ;
z-index : 0 ;
opacity : 0.06 ;
}
. geo-hex :: before {
content : '' ;
position : absolute ;
width : 300 px ; height : 520 px ;
clip-path : polygon ( 50 % 0 % , 100 % 25 % , 100 % 75 % , 50 % 100 % , 0 % 75 % , 0 % 25 % ) ;
background : #fff ;
}
. geo-hex-1 { top : -100 px ; right : -80 px ; transform : rotate ( 15 deg ) ; }
. geo-hex-2 { bottom : 10 % ; left : -120 px ; transform : rotate ( -10 deg ) scale ( 0.7 ) ; }
. geo-hex-3 { top : 60 % ; right : 5 % ; transform : rotate ( 45 deg ) scale ( 0.4 ) ; }
. geo-tri {
position : fixed ;
pointer-events : none ;
z-index : 0 ;
opacity : 0.05 ;
}
. geo-tri :: before {
content : '' ;
position : absolute ;
width : 0 ; height : 0 ;
border-left : 200 px solid transparent ;
border-right : 200 px solid transparent ;
border-bottom : 350 px solid #fff ;
}
. geo-tri-1 { top : 30 % ; left : 5 % ; transform : rotate ( -20 deg ) ; }
. geo-tri-2 { bottom : 20 % ; right : 10 % ; transform : rotate ( 30 deg ) scale ( 0.6 ) ; }
. container {
max-width : 1100 px ;
margin : 0 auto ;
padding : 20 px ;
position : relative ;
z-index : 1 ;
}
header {
text-align : center ;
padding : 70 px 20 px 40 px ;
color : white ;
}
. logo-row {
display : flex ;
align-items : center ;
justify-content : center ;
gap : 24 px ;
margin : 0 auto 20 px ;
filter : drop-shadow ( 0 4 px 12 px rgba ( 0 , 0 , 0 , 0.35 ) ) ;
}
. logo-svg {
width : 100 px ;
display : block ;
}
. logo-png {
width : 80 px ;
height : auto ;
display : block ;
}
. author-badge {
font-size : 0.85 rem ;
opacity : 0.75 ;
margin-top : 4 px ;
letter-spacing : 1 px ;
}
. author-badge strong {
color : #fcd34d ;
}
h1 {
font-size : 3 rem ;
margin-bottom : 12 px ;
text-shadow : 0 3 px 6 px rgba ( 0 , 0 , 0 , 0.4 ) ;
letter-spacing : 2 px ;
}
. subtitle {
font-size : 1.4 rem ;
opacity : 0.92 ;
margin-bottom : 8 px ;
}
. tagline {
font-size : 1 rem ;
letter-spacing : 4 px ;
font-weight : 600 ;
margin-top : 16 px ;
opacity : 0.85 ;
}
/* Widget area */
. widget-container {
margin-bottom : 50 px ;
padding : 30 px 20 px ;
text-align : center ;
background : rgba ( 67 , 20 , 7 , 0.85 ) ;
border-radius : 12 px ;
box-shadow : 0 8 px 32 px rgba ( 0 , 0 , 0 , 0.3 ) ;
}
. osc_pro_color { color : #ffffff !important ; }
. osc_panel_color { background-color : #1e252b !important ; }
. osc_background_color { background-color : #323d47 !important ; }
. osc_border_color { border-color : #455059 !important ; }
. osc_desc_color { color : #d7deea !important ; }
. osc_link_color * { color : #99a0ae !important ; }
/* Log Preview */
. log-preview-section {
max-width : 860 px ;
margin : 50 px auto ;
padding : 30 px ;
}
. log-preview-section h2 {
text-align : center ;
font-size : 1.9 rem ;
margin-bottom : 10 px ;
}
. log-desc {
text-align : center ;
color : var ( - - warm - bg ) ;
margin-bottom : 20 px ;
font-size : 0.95 rem ;
}
. log-terminal {
background : #1a1b26 ;
border : 1 px solid #323d47 ;
border-radius : 12 px ;
padding : 18 px 22 px ;
font-family : 'Cascadia Code' , 'Fira Code' , 'JetBrains Mono' , 'Consolas' , monospace ;
font-size : 0.82 rem ;
line-height : 1.75 ;
box-shadow : inset 0 2 px 12 px rgba ( 0 , 0 , 0 , 0.5 ) , 0 4 px 16 px rgba ( 0 , 0 , 0 , 0.25 ) ;
}
. log-line {
white-space : nowrap ;
overflow : hidden ;
text-overflow : ellipsis ;
color : #d7deea ;
}
. log-time {
color : #565f89 ;
margin-right : 6 px ;
}
. log-level {
display : inline-block ;
min-width : 48 px ;
font-weight : 700 ;
letter-spacing : 0.02 em ;
margin-right : 4 px ;
}
. log-level . info { color : #a9b665 ; }
. log-level . warn { color : #e0af68 ; }
. log-level . debug { color : #7dcfff ; }
. log-level . error { color : #f7768e ; }
/* Cards */
. section-title {
text-align : center ;
color : #fff ;
font-size : 2 rem ;
margin : 50 px 0 30 px ;
text-shadow : 0 2 px 4 px rgba ( 0 , 0 , 0 , 0.3 ) ;
}
. features {
display : grid ;
grid-template-columns : repeat ( auto - fit , minmax ( 280 px , 1 fr ) ) ;
gap : 24 px ;
margin-bottom : 40 px ;
}
. feature-card {
background : var ( - - card - bg ) ;
border-radius : 12 px ;
padding : 28 px ;
box-shadow : 0 8 px 28 px rgba ( 0 , 0 , 0 , 0.18 ) ;
transition : transform 0.3 s , box-shadow 0.3 s ;
border-top : 4 px solid var ( - - orange ) ;
}
. feature-card : hover {
transform : translateY ( -6 px ) ;
box-shadow : 0 14 px 36 px rgba ( 0 , 0 , 0 , 0.25 ) ;
}
. feature-card h3 {
color : var ( - - orange ) ;
font-size : 1.35 rem ;
margin-bottom : 12 px ;
}
. feature-card p {
color : var ( - - text - dim ) ;
line-height : 1.8 ;
}
/* Deploy tutorial */
. deploy-section {
background : var ( - - card - bg ) ;
border-radius : 12 px ;
padding : 40 px ;
box-shadow : 0 8 px 28 px rgba ( 0 , 0 , 0 , 0.18 ) ;
margin-bottom : 40 px ;
}
. deploy-section h2 {
color : var ( - - orange ) ;
font-size : 1.8 rem ;
margin-bottom : 24 px ;
padding-bottom : 12 px ;
border-bottom : 3 px solid var ( - - amber ) ;
}
. deploy-section h3 {
color : var ( - - text ) ;
margin : 24 px 0 10 px ;
font-size : 1.2 rem ;
}
. deploy-section h4 {
color : var ( - - orange ) ;
margin : 18 px 0 8 px ;
font-size : 1.05 rem ;
}
. deploy-section pre {
background : #1c1917 ;
color : #fcd34d ;
padding : 20 px ;
border-radius : 8 px ;
overflow-x : auto ;
font-size : 0.9 rem ;
line-height : 1.6 ;
margin : 10 px 0 16 px ;
}
. deploy-section code {
background : #fff7ed ;
padding : 2 px 6 px ;
border-radius : 4 px ;
color : var ( - - orange ) ;
font-size : 0.92 em ;
}
. deploy-section table {
width : 100 % ;
border-collapse : collapse ;
margin : 12 px 0 20 px ;
}
. deploy-section th , . deploy-section td {
padding : 10 px 14 px ;
text-align : left ;
border-bottom : 1 px solid #fed7aa ;
}
. deploy-section th {
background : #ffedd5 ;
color : var ( - - orange ) ;
font-weight : 600 ;
}
. deploy-section ul { margin : 8 px 0 16 px 20 px ; }
. deploy-section li { margin : 4 px 0 ; color : var ( - - text - dim ) ; }
/* Flow diagram */
. flow-box {
background : #1c1917 ;
border-radius : 8 px ;
padding : 24 px ;
color : #fcd34d ;
font-family : monospace ;
font-size : 0.88 rem ;
line-height : 1.9 ;
white-space : pre ;
overflow-x : auto ;
margin : 16 px 0 ;
}
/* Buttons */
. cta-section {
text-align : center ;
margin : 50 px 0 ;
padding : 30 px 20 px ;
}
. btn {
display : inline-block ;
padding : 14 px 36 px ;
background : white ;
color : var ( - - orange ) ;
text-decoration : none ;
border-radius : 30 px ;
font-weight : bold ;
font-size : 1.05 rem ;
margin : 8 px ;
box-shadow : 0 4 px 14 px rgba ( 0 , 0 , 0 , 0.2 ) ;
transition : all 0.3 s ;
cursor : pointer ;
border : none ;
}
. btn : hover {
transform : scale ( 1.05 ) ;
box-shadow : 0 8 px 22 px rgba ( 0 , 0 , 0 , 0.35 ) ;
}
. btn-primary {
background : #f97316 ;
color : white ;
}
. btn-primary : hover { background : #ea580c ; }
/* Modal */
. modal {
display : none ;
position : fixed ;
top : 0 ; left : 0 ;
width : 100 % ; height : 100 % ;
background : rgba ( 0 , 0 , 0 , 0.7 ) ;
z-index : 1000 ;
justify-content : center ;
align-items : center ;
}
. modal . show { display : flex ; }
. modal-content {
background : var ( - - card - bg ) ;
border-radius : 12 px ;
padding : 36 px ;
max-width : 500 px ;
width : 90 % ;
box-shadow : 0 20 px 60 px rgba ( 0 , 0 , 0 , 0.4 ) ;
position : relative ;
animation : modalIn 0.3 s ease-out ;
}
@ keyframes modalIn {
from { transform : translateY ( -40 px ) ; opacity : 0 ; }
to { transform : translateY ( 0 ) ; opacity : 1 ; }
}
. modal-close {
position : absolute ;
top : 12 px ; right : 18 px ;
font-size : 28 px ;
cursor : pointer ;
color : #9a3412 ;
transition : color 0.3 s ;
}
. modal-close : hover { color : #431407 ; }
. modal-title { color : var ( - - orange ) ; font-size : 1.6 rem ; margin-bottom : 18 px ; }
. modal-body { color : var ( - - text - dim ) ; line-height : 1.8 ; margin-bottom : 20 px ; }
. download-info {
background : #ffedd5 ;
padding : 20 px ;
border-radius : 8 px ;
border-left : 4 px solid var ( - - orange ) ;
}
. download-link { color : var ( - - orange ) ; text-decoration : none ; font-weight : bold ; }
. download-link : hover { text-decoration : underline ; }
. password-info {
margin-top : 14 px ;
padding : 10 px ;
background : #fff3cd ;
border-radius : 6 px ;
color : #92400e ;
}
/* Footer */
footer {
text-align : center ;
padding : 40 px 20 px ;
color : white ;
opacity : 0.8 ;
margin-top : 40 px ;
}
. links { margin-top : 14 px ; }
. links a {
color : white ; text-decoration : none ; margin : 0 14 px ; opacity : 0.9 ;
}
. links a : hover { opacity : 1 ; text-decoration : underline ; }
@ media ( max-width : 640px ) {
h1 { font-size : 2 rem ; }
. deploy-section { padding : 20 px ; }
}
< / style >
< / head >
< body >
<!-- Geometric decorations -->
< div class = "geo-hex geo-hex-1" > < / div >
< div class = "geo-hex geo-hex-2" > < / div >
< div class = "geo-hex geo-hex-3" > < / div >
< div class = "geo-tri geo-tri-1" > < / div >
< div class = "geo-tri geo-tri-2" > < / div >
< div class = "container" >
< header >
< div class = "logo-row" >
2026-06-07 19:50:38 +08:00
< img id = "logoPng" class = "logo-png" src = "" alt = "SW Security" >
2026-06-07 19:35:17 +08:00
< svg class = "logo-svg" viewBox = "0 0 100 80" xmlns = "http://www.w3.org/2000/svg" >
< path d = "M0,1 H100" stroke = "#ffffff" stroke-width = "6" fill = "none" opacity = "0.9" / >
< path d = "M0,20 H30" stroke = "#ffffff" stroke-width = "6" fill = "none" opacity = "0.9" / >
< path d = "M0,40 H30 L40,20 L60,60 L70,40 H100" stroke = "#ffffff" stroke-width = "6" fill = "none" opacity = "0.9" / >
< path d = "M70,60 H100" stroke = "#ffffff" stroke-width = "6" fill = "none" opacity = "0.9" / >
< path d = "M0,79 H100" stroke = "#ffffff" stroke-width = "6" fill = "none" opacity = "0.9" / >
< / svg >
< / div >
< h1 > 🛡️ MineSentinel< / h1 >
< p class = "subtitle" > Minecraft 服务器智能守护进程< / p >
< p class = "tagline" > TCP 检测 · 自动重启 · 防循环冷却< / p >
< p class = "author-badge" > 由 < strong > SCU 团队< / strong > 拥有 · 编写者 < strong > S.A. [@SNOWARE]< / strong > < / p >
< / header >
<!-- Features -->
< div class = "features" >
< div class = "feature-card" >
< h3 > 🔍 高频检测< / h3 >
< p > 每 1.5 秒对 < code > 127.0.0.1:25565< / code > 发起 TCP 连接,毫秒级感知服务器状态变化。< / p >
< / div >
< div class = "feature-card" >
< h3 > 🧠 智能判断< / h3 >
< p > 严格区分端口超时与端口关闭——超时仅记录日志(避免网络抖动误判),关闭才触发重启。< / p >
< / div >
< div class = "feature-card" >
< h3 > ⏳ 冷却期保护< / h3 >
< p > 重启后等待 200 秒,初次启动有 300 秒宽限期,彻底防止 MC 启动缓慢导致循环重启。Watchdog 同步适配(210s)。< / p >
< / div >
< div class = "feature-card" >
< h3 > 🛡️ 重试上限< / h3 >
< p > 连续 10 次重启失败后进入空闲等待模式,每 10 秒检测端口,恢复后自动退出。< / p >
< / div >
< div class = "feature-card" >
< h3 > 🌍 跨平台< / h3 >
< p > 核心逻辑纯 Ruby 实现,支持 systemd / Docker / screen / Windows,轻松适配任意进程管理器。< / p >
< / div >
< div class = "feature-card" >
< h3 > 📝 日志完备< / h3 >
< p > 四级日志(debug / info / warn / error),输出到 systemd journal,排查问题一目了然。< / p >
< / div >
< / div >
<!-- Log Preview -->
< div class = "log-preview-section" >
< h2 > 📋 日志示例< / h2 >
< p class = "log-desc" > 通过 < code > journalctl -u minesentinel -f< / code > 实时查看,以下为一次完整崩溃恢复过程的日志输出:< / p >
< div class = "log-terminal" >
< div class = "log-line" > < span class = "log-time" > 18:16:17< / span > < span class = "log-level debug" > DEBUG< / span > self_diag: TCP check OK — 0.0002s< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:17< / span > < span class = "log-level debug" > DEBUG< / span > mainloop: Server health check passed.< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:18< / span > < span class = "log-level debug" > DEBUG< / span > self_diag: TCP check OK — 0.0003s< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:18< / span > < span class = "log-level debug" > DEBUG< / span > mainloop: Server health check passed.< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:20< / span > < span class = "log-level warn" > WARN< / span > self_diag: TCP port closed — server is down.< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:21< / span > < span class = "log-level warn" > WARN< / span > mainloop: Server health check FAILED: Server died for unknown reason, and will be restarted.< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:21< / span > < span class = "log-level warn" > WARN< / span > mainloop: Action: Record → Server died!< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:21< / span > < span class = "log-level info" > INFO< / span > mainloop: Action: ForceResetServerProcess triggered.< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:21< / span > < span class = "log-level info" > INFO< / span > reset: Attempt #1 to reset Minecraft server.< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:21< / span > < span class = "log-level info" > INFO< / span > reset: Spawning 'systemctl restart minecraft' (PID will be captured)...< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:21< / span > < span class = "log-level debug" > DEBUG< / span > reset: systemctl restart spawned with new PID.< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:51< / span > < span class = "log-level warn" > WARN< / span > reset: 'systemctl restart' timed out after 30s. Force-killing process...< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:51< / span > < span class = "log-level warn" > WARN< / span > reset: Running 'systemctl kill minecraft' (last resort)...< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:52< / span > < span class = "log-level info" > INFO< / span > reset: Running 'systemctl start minecraft' (rebirth)...< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:52< / span > < span class = "log-level info" > INFO< / span > reset: Force-reset sequence completed.< / div >
< div class = "log-line" > < span class = "log-time" > 18:16:52< / span > < span class = "log-level info" > INFO< / span > mainloop: Cooling down 200s for server startup...< / div >
< div class = "log-line" style = "opacity:.5;" > < span class = "log-time" > ... ... ...< / span > < / div >
< div class = "log-line" > < span class = "log-time" > 18:20:12< / span > < span class = "log-level info" > INFO< / span > mainloop: Cooldown finished, resuming monitoring.< / div >
< div class = "log-line" > < span class = "log-time" > 18:20:14< / span > < span class = "log-level debug" > DEBUG< / span > self_diag: TCP check OK — 0.0002s< / div >
< div class = "log-line" > < span class = "log-time" > 18:20:15< / span > < span class = "log-level debug" > DEBUG< / span > mainloop: Server health check passed.< / div >
< / div >
< p class = "log-note" style = "margin-top:14px;color:var(--text-dim);font-size:0.88em;" > 💡 日志中 PID、精确时间戳等敏感信息已脱敏。实际输出格式与 < code > journald< / code > 一致,支持 < code > --since< / code > 、< code > -f< / code > 等标准过滤参数。< / p >
< / div >
<!-- Deploy Tutorial -->
< div class = "deploy-section" >
< h2 > 📦 部署教程< / h2 >
< h3 > 1. 环境要求< / h3 >
< table >
< tr > < th > 项目< / th > < th > 说明< / th > < / tr >
< tr > < td > 操作系统< / td > < td > Linux(需 systemd),也支持 Windows< / td > < / tr >
< tr > < td > Ruby< / td > < td > >= 3.0< / td > < / tr >
< tr > < td > 权限< / td > < td > root( systemctl 需要)< / td > < / tr >
< tr > < td > MC 服务< / td > < td > 已注册为 systemd 服务,默认名 < code > minecraft< / code > < / td > < / tr >
< / table >
< h3 > 2. 获取源码< / h3 >
< p style = "margin-bottom:6px;" > 方式一:Git 克隆(推荐,仅拉取必要文件,排除仓库冗余)< / p >
< pre > git clone --depth 1 --single-branch \
https://gitee.com/SCU_team/mine-sentinel.git \
/opt/minecraft/sentinel
# --depth 1 仅拉取最新提交,不下载历史记录
# --single-branch 仅拉取 master 分支< / pre >
< p style = "margin-bottom:6px;" > 方式二:手动复制< / p >
< pre > mkdir -p /opt/minecraft/sentinel
cp main.rb method_executor.rb server_status_detector.rb \
2026-06-08 10:33:36 +08:00
systemd_notifier.rb config.rb \
2026-06-07 19:35:17 +08:00
/opt/minecraft/sentinel/< / pre >
< h3 > 3. 手动测试< / h3 >
< pre > cd /opt/minecraft/sentinel
ruby main.rb
# 调试模式: LOG_LEVEL=debug ruby main.rb< / pre >
< h3 > 4. 注册 systemd 服务< / h3 >
< p > 项目源码中已提供 < code > minesentinel.service< / code > ,直接复制:< / p >
< pre > cp minesentinel.service /etc/systemd/system/< / pre >
< p > 单元文件内容:< / p >
< pre > [Unit]
Description=MineSentinel Minecraft Server Monitor
After=network.target
Before=minecraft.service
Wants=minecraft.service
[Service]
Type=simple
WorkingDirectory=/opt/minecraft/sentinel
ExecStart=/usr/bin/ruby /opt/minecraft/sentinel/main.rb
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
#Environment=LOG_LEVEL=debug
WatchdogSec=210
[Install]
WantedBy=multi-user.target< / pre >
< h4 > 🔗 启动顺序< / h4 >
< p style = "margin-bottom:10px;" > MineSentinel 通过 < code > Before=minecraft.service< / code > 确保先于 MC 启动,消除守护盲区。首次启动有 < strong > 300 秒宽限期< / strong > 等待端口就绪:< / p >
< div class = "flow-box" > 开机 → network.target
│
├─ MineSentinel 启动(最先)
│ └─ 进入 300s 宽限期,等待 MC 端口就绪
│
└─ minecraft 随后启动(Before=)
└─ 端口打开 → MineSentinel 恢复正常监控< / div >
< pre > systemctl daemon-reload
systemctl enable minesentinel # 同时触发 minecraft( Wants=)
systemctl start minesentinel< / pre >
< h3 > 5. 查看日志< / h3 >
< pre > journalctl -u minesentinel -f # 实时
journalctl -u minesentinel -u minecraft -f # 双服务合并< / pre >
< h3 > ⚙️ 可调参数< / h3 >
< table >
< tr > < th > 参数< / th > < th > 文件< / th > < th > 行< / th > < th > 默认< / th > < / tr >
2026-06-08 10:33:36 +08:00
< tr > < td > 初始宽限期< / td > < td > config.rb< / td > < td > 1< / td > < td > 300 s< / td > < / tr >
< tr > < td > 冷却期< / td > < td > config.rb< / td > < td > 3< / td > < td > 200 s< / td > < / tr >
< tr > < td > 尝试次数< / td > < td > config.rb< / td > < td > 2< / td > < td > 3 次< / td > < / tr >
2026-06-08 10:37:12 +08:00
< tr > < td > 检测间隔< / td > < td > config.rb< / td > < td > 4< / td > < td > 1.5 s< / td > < / tr >
2026-06-07 19:35:17 +08:00
< tr > < td > systemctl 超时< / td > < td > method_executor.rb< / td > < td > 17< / td > < td > 30 s< / td > < / tr >
< tr > < td > 最大重试< / td > < td > method_executor.rb< / td > < td > 23< / td > < td > 10 次< / td > < / tr >
< tr > < td > 检测端口< / td > < td > server_status_detector.rb< / td > < td > 60< / td > < td > 25565< / td > < / tr >
< / table >
< h3 > 🔄 工作流程< / h3 >
< div class = "flow-box" > MineSentinel 启动:
└─ 300s 宽限期 → 等待 MC 端口就绪(避免误判)
每 1.5 秒循环:
├─ TCP 连接 127.0.0.1:25565
├─ 端口开放 → 继续循环
├─ 端口超时 → 仅记录日志(不重启)
└─ 端口关闭 → 触发重启 → 冷却 200 秒
└─ 连续 10 次失败 → 空闲等待< / div >
< h3 > 🪟 Windows / Docker / 其他场景< / h3 >
< ul >
< li > < strong > Docker: < / strong > 替换重启命令为 < code > spawn "docker restart mc-server"< / code > < / li >
< li > < strong > screen: < / strong > < code > system "screen -S mc -X quit"; system "screen -dmS mc java ..."< / code > < / li >
< li > < strong > Windows: < / strong > 删除 root 检查,替换为 < code > spawn "cmd /c start /B java ..."< / code > ,日志输出到文件< / li >
< li > < strong > 监控其他服务:< / strong > 修改 < code > test_port< / code > 的 IP 和端口即可< / li >
< / ul >
< p style = "margin-top: 12px; color: var(--text-dim);" > 详细适配指南见 < a href = "https://gitee.com/SCU_team/mine-sentinel/blob/master/DEPLOY.md" style = "color: var(--orange);" > DEPLOY.md< / a > < / p >
< / div >
<!-- Gitee Widget -->
< div class = "widget-container" >
< div id = "osc-gitee-widget-tag" > < / div >
< / div >
<!-- CTA -->
< div class = "cta-section" >
< button onclick = "openModal()" class = "btn btn-primary" > ⬇️ 获取 MineSentinel< / button >
< a href = "https://gitee.com/SCU_team/mine-sentinel" class = "btn" > ⭐ Gitee 仓库< / a >
< a href = "https://gitee.com/SCU_team/mine-sentinel/blob/master/DEPLOY.md" class = "btn" > 📖 完整文档< / a >
< / div >
<!-- Download Modal -->
< div id = "dlModal" class = "modal" >
< div class = "modal-content" >
< span class = "modal-close" onclick = "closeModal()" > × < / span >
< h2 class = "modal-title" > ⬇️ 获取 MineSentinel< / h2 >
< div class = "modal-body" >
< div class = "download-info" >
< p > < strong > Git 克隆:< / strong > < / p >
< pre style = "margin:8px 0;font-size:0.85rem;" > git clone https://gitee.com/SCU_team/mine-sentinel.git< / pre >
< p style = "margin-top:10px;" > < strong > 直接下载:< / strong > < / p >
< p > < a href = "https://gitee.com/SCU_team/mine-sentinel/repository/archive/master.zip" target = "_blank" class = "download-link" > 📦 下载 ZIP 压缩包< / a > < / p >
< div class = "password-info" style = "margin-top: 12px;" >
< strong > 📋 要求:< / strong > Ruby >= 3.0 · Linux (systemd) 或 Windows
< / div >
< / div >
< p style = "margin-top: 16px; color: var(--text-dim); font-size: 0.9em;" > 💡 部署前请阅读 < a href = "https://gitee.com/SCU_team/mine-sentinel/blob/master/DEPLOY.md" style = "color: var(--orange);" > DEPLOY.md< / a > 。< / p >
< / div >
< / div >
< / div >
< footer >
< p > © 2026 MineSentinel — S.A. SNOWARE-SCU< / p >
< p > 源码采用 < a href = "http://license.coscl.org.cn/MulanPubL-2.0" style = "color:#fcd34d;" > MulanPubL v2.0< / a > · 品牌标识(Logo/SVG)保留所有权利< / p >
< div class = "links" >
< a href = "https://gitee.com/SCU_team/mine-sentinel" > Gitee< / a >
< a href = "https://gitee.com/SCU_team/mine-sentinel/issues" > 问题反馈< / a >
< a href = "https://gitee.com/SCU_team/mine-sentinel/blob/master/DEPLOY.md" > 部署文档< / a >
< / div >
2026-06-07 20:41:14 +08:00
< script >
var SWSEC _B64 = "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
(function() {
var e = document.getElementById(" logoPng ");
if (!e) return;
var binary = atob(SWSEC_B64);
var bytes = new Uint8Array(binary.length);
for (var i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
var blob = new Blob([bytes], { type: " image / png " } ) ;
e . src = URL . createObjectURL ( blob ) ;
} ) ( ) ;
< / script > < / footer >
2026-06-07 19:35:17 +08:00
< / div >
< script >
function openModal ( ) {
document . getElementById ( 'dlModal' ) . classList . add ( 'show' ) ;
}
function closeModal ( ) {
document . getElementById ( 'dlModal' ) . classList . remove ( 'show' ) ;
}
window . onclick = function ( e ) {
if ( e . target === document . getElementById ( 'dlModal' ) ) closeModal ( ) ;
}
2026-06-07 20:41:14 +08:00
2026-06-07 19:35:17 +08:00
< / script >
< / body >
< / html >