Files
sentinel/OfficialWebsite/index.html
T
2026-06-07 19:45:13 +08:00

752 lines
32 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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(160deg, #f97316 0%, #ea580c 40%, #dc2626 100%);
min-height: 100vh;
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(30deg, transparent, transparent 80px, rgba(255,255,255,0.03) 80px, rgba(255,255,255,0.03) 82px),
repeating-linear-gradient(-60deg, transparent, transparent 120px, rgba(255,255,255,0.04) 120px, rgba(255,255,255,0.04) 122px);
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: 300px; height: 520px;
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
background: #fff;
}
.geo-hex-1 { top: -100px; right: -80px; transform: rotate(15deg); }
.geo-hex-2 { bottom: 10%; left: -120px; transform: rotate(-10deg) scale(0.7); }
.geo-hex-3 { top: 60%; right: 5%; transform: rotate(45deg) 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: 200px solid transparent;
border-right: 200px solid transparent;
border-bottom: 350px solid #fff;
}
.geo-tri-1 { top: 30%; left: 5%; transform: rotate(-20deg); }
.geo-tri-2 { bottom: 20%; right: 10%; transform: rotate(30deg) scale(0.6); }
.container {
max-width: 1100px;
margin: 0 auto;
padding: 20px;
position: relative;
z-index: 1;
}
header {
text-align: center;
padding: 70px 20px 40px;
color: white;
}
.logo-row {
display: flex;
align-items: center;
justify-content: center;
gap: 24px;
margin: 0 auto 20px;
filter: drop-shadow(0 4px 12px rgba(0,0,0,0.35));
}
.logo-svg {
width: 100px;
display: block;
}
.logo-png {
width: 80px;
height: auto;
display: block;
}
.author-badge {
font-size: 0.85rem;
opacity: 0.75;
margin-top: 4px;
letter-spacing: 1px;
}
.author-badge strong {
color: #fcd34d;
}
h1 {
font-size: 3rem;
margin-bottom: 12px;
text-shadow: 0 3px 6px rgba(0,0,0,0.4);
letter-spacing: 2px;
}
.subtitle {
font-size: 1.4rem;
opacity: 0.92;
margin-bottom: 8px;
}
.tagline {
font-size: 1rem;
letter-spacing: 4px;
font-weight: 600;
margin-top: 16px;
opacity: 0.85;
}
/* Widget area */
.widget-container {
margin-bottom: 50px;
padding: 30px 20px;
text-align: center;
background: rgba(67, 20, 7, 0.85);
border-radius: 12px;
box-shadow: 0 8px 32px 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: 860px;
margin: 50px auto;
padding: 30px;
}
.log-preview-section h2 {
text-align: center;
font-size: 1.9rem;
margin-bottom: 10px;
}
.log-desc {
text-align: center;
color: var(--warm-bg);
margin-bottom: 20px;
font-size: 0.95rem;
}
.log-terminal {
background: #1a1b26;
border: 1px solid #323d47;
border-radius: 12px;
padding: 18px 22px;
font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', monospace;
font-size: 0.82rem;
line-height: 1.75;
box-shadow: inset 0 2px 12px rgba(0,0,0,0.5), 0 4px 16px rgba(0,0,0,0.25);
}
.log-line {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #d7deea;
}
.log-time {
color: #565f89;
margin-right: 6px;
}
.log-level {
display: inline-block;
min-width: 48px;
font-weight: 700;
letter-spacing: 0.02em;
margin-right: 4px;
}
.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: 2rem;
margin: 50px 0 30px;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
margin-bottom: 40px;
}
.feature-card {
background: var(--card-bg);
border-radius: 12px;
padding: 28px;
box-shadow: 0 8px 28px rgba(0,0,0,0.18);
transition: transform 0.3s, box-shadow 0.3s;
border-top: 4px solid var(--orange);
}
.feature-card:hover {
transform: translateY(-6px);
box-shadow: 0 14px 36px rgba(0,0,0,0.25);
}
.feature-card h3 {
color: var(--orange);
font-size: 1.35rem;
margin-bottom: 12px;
}
.feature-card p {
color: var(--text-dim);
line-height: 1.8;
}
/* Deploy tutorial */
.deploy-section {
background: var(--card-bg);
border-radius: 12px;
padding: 40px;
box-shadow: 0 8px 28px rgba(0,0,0,0.18);
margin-bottom: 40px;
}
.deploy-section h2 {
color: var(--orange);
font-size: 1.8rem;
margin-bottom: 24px;
padding-bottom: 12px;
border-bottom: 3px solid var(--amber);
}
.deploy-section h3 {
color: var(--text);
margin: 24px 0 10px;
font-size: 1.2rem;
}
.deploy-section h4 {
color: var(--orange);
margin: 18px 0 8px;
font-size: 1.05rem;
}
.deploy-section pre {
background: #1c1917;
color: #fcd34d;
padding: 20px;
border-radius: 8px;
overflow-x: auto;
font-size: 0.9rem;
line-height: 1.6;
margin: 10px 0 16px;
}
.deploy-section code {
background: #fff7ed;
padding: 2px 6px;
border-radius: 4px;
color: var(--orange);
font-size: 0.92em;
}
.deploy-section table {
width: 100%;
border-collapse: collapse;
margin: 12px 0 20px;
}
.deploy-section th, .deploy-section td {
padding: 10px 14px;
text-align: left;
border-bottom: 1px solid #fed7aa;
}
.deploy-section th {
background: #ffedd5;
color: var(--orange);
font-weight: 600;
}
.deploy-section ul { margin: 8px 0 16px 20px; }
.deploy-section li { margin: 4px 0; color: var(--text-dim); }
/* Flow diagram */
.flow-box {
background: #1c1917;
border-radius: 8px;
padding: 24px;
color: #fcd34d;
font-family: monospace;
font-size: 0.88rem;
line-height: 1.9;
white-space: pre;
overflow-x: auto;
margin: 16px 0;
}
/* Buttons */
.cta-section {
text-align: center;
margin: 50px 0;
padding: 30px 20px;
}
.btn {
display: inline-block;
padding: 14px 36px;
background: white;
color: var(--orange);
text-decoration: none;
border-radius: 30px;
font-weight: bold;
font-size: 1.05rem;
margin: 8px;
box-shadow: 0 4px 14px rgba(0,0,0,0.2);
transition: all 0.3s;
cursor: pointer;
border: none;
}
.btn:hover {
transform: scale(1.05);
box-shadow: 0 8px 22px 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: 12px;
padding: 36px;
max-width: 500px;
width: 90%;
box-shadow: 0 20px 60px rgba(0,0,0,0.4);
position: relative;
animation: modalIn 0.3s ease-out;
}
@keyframes modalIn {
from { transform: translateY(-40px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.modal-close {
position: absolute;
top: 12px; right: 18px;
font-size: 28px;
cursor: pointer;
color: #9a3412;
transition: color 0.3s;
}
.modal-close:hover { color: #431407; }
.modal-title { color: var(--orange); font-size: 1.6rem; margin-bottom: 18px; }
.modal-body { color: var(--text-dim); line-height: 1.8; margin-bottom: 20px; }
.download-info {
background: #ffedd5;
padding: 20px;
border-radius: 8px;
border-left: 4px solid var(--orange);
}
.download-link { color: var(--orange); text-decoration: none; font-weight: bold; }
.download-link:hover { text-decoration: underline; }
.password-info {
margin-top: 14px;
padding: 10px;
background: #fff3cd;
border-radius: 6px;
color: #92400e;
}
/* Footer */
footer {
text-align: center;
padding: 40px 20px;
color: white;
opacity: 0.8;
margin-top: 40px;
}
.links { margin-top: 14px; }
.links a {
color: white; text-decoration: none; margin: 0 14px; opacity: 0.9;
}
.links a:hover { opacity: 1; text-decoration: underline; }
@media (max-width: 640px) {
h1 { font-size: 2rem; }
.deploy-section { padding: 20px; }
}
</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">
<img class="logo-png" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVAAAAFECAYAAABxr2ZUAAAAAXNSR0IArs4c6QA
AARnQU1BAACxjwv8YQUAAAAJcEhZcwAAHYYAAB2GAV2iE4EAAAGHaVRYdFhNTDpj
b20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49J++7vycgaWQ9J1c1TTBN
cENlaGlIenJlU3pOVGN6a2M5ZCc/Pg0KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9i
ZTpuczptZXRhLyI+PHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9y
Zy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj48cmRmOkRlc2NyaXB0aW9uIHJk
ZjphYm91dD0idXVpZDpmYWY1YmRkNS1iYTNkLTExZGEtYWQzMS1kMzNkNzUxODJm
MWIiIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIj48
dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPjwvcmRmOkRlc2Ny
aXB0aW9uPjwvcmRmOlJERj48L3g6eG1wbWV0YT4NCjw/eHBhY2tldCBlbmQ9J3cn
Pz4slJgLAACPOElEQVR4Xuz9d5wteV3njz8/oapO6Nw3zp3ADExAchDRxbCCiLuC
6Ye7xl2/oK67KiJ8RYWvsLIoIEFZEUWWsKhf/Q6CKzkICoMwpIFhgBkmx5v7dvdJ
FT7h98en6vTpc/tOomH63vt5zuM8Tvc5VdU159Z51fvzjsJ774lEIpHIfUZOvxCJ
RCKRe0cU0EgkErmfRAGNRCKR+0kU0EgkErmfRAGNRCKR+0kU0EgkErmfRAGNRCKR
+0kU0EgkErmfRAGNRCKR+0kU0EgkErmfRAGNRCKR+0kU0EgkErmfRAGNRCKR+0kU
0EgkErmfRAGNRCKR+0kU0EgkErmfRAGNRCKR+0kU0EgkErmfRAGNRCKR+0kU0Egk
ErmfRAGNRCKR+0kU0EgkErmfRAGNRCKR+0kU0EgkErmfRAGNRCKR+0kU0EgkErmf
RAGNRCKR+4nw3vvpFyORyM6iKCx33DXgxKrFeYnS4AFbWsCDdTgJymu8JPwuQAE6
S9DSU1qLq0oqZ5CAoGTf3lkuuGAXw+GQbrc7/Wcj90AU0Ehkh3Pk2JAvf3kVIVvg
JV6A1hKpwBmL9x7nHCARQiCEwHtP89XWWqK1BhzGllhrcM4hZYnND/HkJ38HQgqG
wyGdTmf6z0fuhriEj0R2MHfctc6//uvtrK87+j3P+rplMBTkhWKUS3pDz2Cw+dHv
u/ph6PUqer2KwcCSF1CWijyXlKWkqgRpa5b19SEAz3/+86f/fOQeiBZoJLKD+eCH
b+LoMZAiA5ngLCRZSpIojK0Ah3MO58L2QggAvHW1BerQWpNmGqUExhiKIgfhSLWl
kw0Rfo3vf/J30W5rqqpCymhX3VviJxWJ7FBWV3PuOmjp9TXrfUevV5IXMBpaBv2K
Ue7o9Q39gWU4Co/B0DEYOoZDx2BgGeWe4Sj8PBhYhkNHUQpGI0+v71hZgbzsIDVY
a7nyyiunTyNyN0QBjUR2KHlpObbq6I8E/WFFf1gxHBgGo/AYTjwGw4rB0DIaGkZD
w2DkGIwM/fWKQb9kOLCMhp585OptXHiMBMORx9Xr0He/+93TpxG5G6KARiI7lKKo
GA1L+oOC/qB+HhYMBxWjYUU+MsEaHRqGA8NwUNVCWjEYVPQHJev9gl6/oj8s6Q8L
BqOSwahiMKoYjkrKsqIoivHfXF9f33QOkbsnCmgkskNx1jMcVcGiHBiGA8twaBmN
HKPcjq3P8H793sAzGniGAxOeR5bhoGLYb6xTx2jQWKGWIrfkeQG1D3V9fX0cvY/c
M1FAI5EdivMw6DnWeyXr/Yp+vwxiWD9GQ8ewb+kPLP2hpTcwDIZ2/OgPTPCFNr/3
68egFtxBsHCHg3K8hK+qavo0IndDFNBIZIdiKs9gWAXLc1AxGDmGY+uzFsJRsCqH
g4rRwDEYmvoRXgtWq2PQCO4gWLSjYfCR5oUlz0tkCN5jjJk+jcjdEAU0EtmhfPFL
x1jvGfqDcmwxDoZ1EGkYfJ6jWhwHk/7P+tEfVKz3CnqDkv6wjsKPQoR+OHSMhpay
dBRFFcqaCJH4yL0nCmgkskP5h3ffSH+Q0x+E6PtwaBnVj42AURn8nUPLcFBOvF8G
sR0UDPpV+H1Uko+a4FOwRMPvBY1uVlUVfaD3gSigkcgOpSgFggxE
usaural
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
/F94E0UXQn5kNQAAAABJRU5ErkJggg==" alt="SW Security">
<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>rootsystemctl 需要)</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 \
/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 # 同时触发 minecraftWants=
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>
<tr><td>初始宽限期</td><td>main.rb</td><td>31</td><td>300 s</td></tr>
<tr><td>检测间隔</td><td>main.rb</td><td>69</td><td>1.5 s</td></tr>
<tr><td>冷却期</td><td>main.rb</td><td>58</td><td>200 s</td></tr>
<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()">&times;</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>&copy; 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>
</footer>
</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();
}
</script>
</body>
</html>