release: v0.2.0
Some checks failed
Release / Build & Release (push) Has been cancelled
Some checks failed
Release / Build & Release (push) Has been cancelled
Comprehensive release containing structural, UX, and behavioral upgrades since v0.1.0: 1. Namespace Transition: Renamed core executable and project namespaces from 'smart-monitor' to 'smart-shutdown'. 2. Objective Vocabulary Refactoring: Normalized output strings and logging descriptors system-wide to a strict, professional tone. 3. Advanced Status Query: 'status' subcommand now retrieves the parsed configuration, log locations/sizes, and tails the last 10 lines of the local log file. 4. Runtime Configuration Setter: Introduced 'config set' subcommand to modify the configuration file with strict type validations. 5. Auto-System Deployment: Remapped 'install' to clone the executable into system domains and register global PATH variables. 6. Cleaner Removal: 'uninstall' purges binary clones and clears environmental variables, leaving zero traces. 7. Documentation Rewrite: Generated an objective README file featuring copy-paste ready Markdown blocks.
This commit is contained in:
@@ -10,113 +10,96 @@ import (
|
||||
"smart-shutdown/pkg/system"
|
||||
)
|
||||
|
||||
// Run 开启核心状态机循环监控,接收 ctx 以便主程序或者服务管理器控制安全退出
|
||||
func Run(ctx context.Context, cfg *config.Config) {
|
||||
logger.Info("========== 智能关机监控已启动 ==========")
|
||||
logger.Info("监控目标: %s", cfg.TargetIP)
|
||||
logger.Info("监控窗口: %d秒", cfg.MonitorWindowSeconds)
|
||||
logger.Info("关机倒计时: %d秒", cfg.ShutdownCountdown)
|
||||
logger.Info("启动后台网络监控")
|
||||
logger.Info("监控目标 IP: %s", cfg.TargetIP)
|
||||
logger.Info("故障判定窗口: %d秒", cfg.MonitorWindowSeconds)
|
||||
logger.Info("关机倒计时阈值: %d秒", cfg.ShutdownCountdown)
|
||||
|
||||
var failureStartTime time.Time
|
||||
var inFailureWindow bool = false
|
||||
|
||||
normalStatusCounter := 0
|
||||
// 每 24 次正常检测输出一次日志(约 6 分钟)
|
||||
const normalStatusLogInterval = 24
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
logger.Info("========== 收到停止信号,退出监控 ==========")
|
||||
logger.Info("接收到系统停止指令, 退出核心调度监控")
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
isOnline := pinger.Ping(cfg.TargetIP, 3) // 3 秒超时探测一次
|
||||
isOnline := pinger.Ping(cfg.TargetIP, 3)
|
||||
|
||||
if isOnline {
|
||||
if inFailureWindow {
|
||||
logger.Succ("网络连接已恢复!重置断网计时器。")
|
||||
logger.Succ("网络连通性恢复, 监控窗口重置")
|
||||
inFailureWindow = false
|
||||
normalStatusCounter = 0
|
||||
} else {
|
||||
normalStatusCounter++
|
||||
if normalStatusCounter >= normalStatusLogInterval {
|
||||
logger.Info("网络连接持续正常(已检测 %d 次)", normalStatusCounter)
|
||||
logger.Info("网络探测状态正常 (定期状态更新)")
|
||||
normalStatusCounter = 0
|
||||
}
|
||||
}
|
||||
|
||||
// 正常状态下休眠等待下一次探测
|
||||
time.Sleep(time.Duration(cfg.NormalPingInterval) * time.Second)
|
||||
|
||||
} else {
|
||||
logger.Fail("Ping 测试失败 - 目标: %s", cfg.TargetIP)
|
||||
logger.Warn("目标节点未响应探针包: %s", cfg.TargetIP)
|
||||
|
||||
if !inFailureWindow {
|
||||
// 首次断网
|
||||
failureStartTime = time.Now()
|
||||
inFailureWindow = true
|
||||
logger.Warn("网络首次中断,开始进入监控窗口计时。")
|
||||
logger.Warn("触发网络状态失效, 开始累计中断时间监控")
|
||||
}
|
||||
|
||||
// 计算当前断网累计时间
|
||||
failureDuration := time.Since(failureStartTime).Seconds()
|
||||
|
||||
if int(failureDuration) >= cfg.MonitorWindowSeconds {
|
||||
logger.Crit("网络持续中断已超过 %d 秒,触发关机流程!", cfg.MonitorWindowSeconds)
|
||||
logger.Crit("持续中断时长超越设定的阈值上限 (%d秒), 进入关机响应流程", cfg.MonitorWindowSeconds)
|
||||
|
||||
// 进入倒计时阶段,倒计时期间高频检测(阻塞调用)
|
||||
shutdownCancelled := startCountdown(ctx, cfg.TargetIP, cfg.ShutdownCountdown)
|
||||
|
||||
if !shutdownCancelled {
|
||||
logger.Crit("倒计时结束,执行最终关机!")
|
||||
logger.Crit("倒计时时限完毕, 开始下发系统级级终态关机指令")
|
||||
system.ExecuteShutdown()
|
||||
// 关机指令发出,理论上系统即将终止进程,为了优雅,此处也退出
|
||||
return
|
||||
} else {
|
||||
// 倒计时中途网络恢复被取消了,重置状态重新进入监控环节
|
||||
inFailureWindow = false
|
||||
}
|
||||
} else {
|
||||
// 还在容忍窗口期内,仅仅打印日志并休眠
|
||||
logger.Info("网络已持续中断 %.0f / %d 秒,继续监控...", failureDuration, cfg.MonitorWindowSeconds)
|
||||
logger.Info("网络持续断失: %.0f/%d 秒", failureDuration, cfg.MonitorWindowSeconds)
|
||||
time.Sleep(time.Duration(cfg.NormalPingInterval) * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// startCountdown 执行关机前倒计时的轮询,如果中途恢复网络返回 true (代表取消关机)。
|
||||
// 返回 false 代表断网到底,坚决关机。
|
||||
func startCountdown(ctx context.Context, targetIP string, countdownSec int) bool {
|
||||
logger.Warn("============================================")
|
||||
logger.Warn("准备关机!倒计时 %d 秒期间将快速探测网络...", countdownSec)
|
||||
logger.Warn("============================================")
|
||||
logger.Warn("执行系统关机倒计时流程 (预设: %d秒)...", countdownSec)
|
||||
|
||||
endTime := time.Now().Add(time.Duration(countdownSec) * time.Second)
|
||||
// 倒计时期间提高探测频率:每 3 秒一次
|
||||
ticker := time.NewTicker(3 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
remaining := int(time.Until(endTime).Seconds())
|
||||
if remaining <= 0 {
|
||||
return false // 时间到,确认无法恢复
|
||||
return false
|
||||
}
|
||||
|
||||
logger.Warn("距离关机还有 %d 秒... 正在高频检测网络", remaining)
|
||||
logger.Warn("距离关机指令处分剩余: %d 秒", remaining)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
logger.Info("收到退出系统服务信号,中止倒计时关机!")
|
||||
logger.Info("挂起关机倒计流程:收到系统强制干预信号")
|
||||
return true
|
||||
case <-ticker.C:
|
||||
// 高频重试检测网络
|
||||
if pinger.Ping(targetIP, 3) {
|
||||
logger.Succ("============================================")
|
||||
logger.Succ("网络在倒计时期间奇迹般地恢复了!立刻取消关机!")
|
||||
logger.Succ("============================================")
|
||||
logger.Succ("倒计时周期内网络指标恢复, 全局关机流程已被重置并取消")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user