520 lines
18 KiB
PowerShell
520 lines
18 KiB
PowerShell
<#
|
||
.SYNOPSIS
|
||
智能网络监控脚本 - 系统级部署脚本
|
||
|
||
.DESCRIPTION
|
||
将脚本部署到系统级目录,配置为开机自启动,无需用户登录
|
||
|
||
部署位置:
|
||
- 程序文件: C:\Program Files\SmartNetworkMonitor\
|
||
- 配置文件: C:\ProgramData\SmartNetworkMonitor\
|
||
- 日志文件: C:\ProgramData\SmartNetworkMonitor\logs\
|
||
#>
|
||
|
||
# 定义系统级路径
|
||
$ProgramPath = "C:\Program Files\SmartNetworkMonitor"
|
||
$DataPath = "C:\ProgramData\SmartNetworkMonitor"
|
||
$LogPath = "$DataPath\logs"
|
||
|
||
Write-Host "==========================================" -ForegroundColor Cyan
|
||
Write-Host "智能网络监控脚本 - 系统级部署" -ForegroundColor Cyan
|
||
Write-Host "==========================================" -ForegroundColor Cyan
|
||
Write-Host ""
|
||
|
||
Write-Host "部署计划:" -ForegroundColor Yellow
|
||
Write-Host "- 程序目录: $ProgramPath" -ForegroundColor White
|
||
Write-Host "- 数据目录: $DataPath" -ForegroundColor White
|
||
Write-Host "- 日志目录: $LogPath" -ForegroundColor White
|
||
Write-Host ""
|
||
|
||
# 检查源文件
|
||
$SourcePath = $PSScriptRoot
|
||
$RequiredFiles = @(
|
||
"smart_shutdown.ps1"
|
||
)
|
||
|
||
foreach ($file in $RequiredFiles) {
|
||
if (-not (Test-Path -Path (Join-Path $SourcePath $file))) {
|
||
Write-Error "找不到必需文件: $file"
|
||
exit 1
|
||
}
|
||
}
|
||
|
||
Write-Host "[OK] 源文件检查完成" -ForegroundColor Green
|
||
|
||
# 创建目录结构
|
||
Write-Host "正在创建目录结构..." -ForegroundColor Yellow
|
||
|
||
try {
|
||
# 创建程序目录
|
||
if (-not (Test-Path -Path $ProgramPath)) {
|
||
New-Item -Path $ProgramPath -ItemType Directory -Force | Out-Null
|
||
Write-Host "[OK] 创建程序目录: $ProgramPath" -ForegroundColor Green
|
||
}
|
||
|
||
# 创建数据目录
|
||
if (-not (Test-Path -Path $DataPath)) {
|
||
New-Item -Path $DataPath -ItemType Directory -Force | Out-Null
|
||
Write-Host "[OK] 创建数据目录: $DataPath" -ForegroundColor Green
|
||
}
|
||
|
||
# 创建日志目录
|
||
if (-not (Test-Path -Path $LogPath)) {
|
||
New-Item -Path $LogPath -ItemType Directory -Force | Out-Null
|
||
Write-Host "[OK] 创建日志目录: $LogPath" -ForegroundColor Green
|
||
}
|
||
}
|
||
catch {
|
||
Write-Error "创建目录失败: $($_.Exception.Message)"
|
||
exit 1
|
||
}
|
||
|
||
# 创建系统优化版的主脚本
|
||
Write-Host "正在创建系统版本的脚本..." -ForegroundColor Yellow
|
||
|
||
$SystemScriptContent = @"
|
||
#Requires -Version 5.1
|
||
|
||
<#
|
||
.SYNOPSIS
|
||
智能网络监控脚本 - 系统服务版本
|
||
|
||
.DESCRIPTION
|
||
系统级网络监控脚本,在网络持续中断时自动关机
|
||
|
||
特点:
|
||
- 开机自启动,无需用户登录
|
||
- 日志存储在系统数据目录
|
||
- 优化的错误处理和权限管理
|
||
#>
|
||
|
||
# ==================== 系统级配置参数 ====================
|
||
|
||
# 监控的目标IP地址
|
||
[string]`$TargetIP = "192.168.3.3"
|
||
|
||
# 正常监控时的ping间隔(秒)
|
||
[int]`$NormalPingInterval = 15
|
||
|
||
# 监控窗口时长(秒) - 在此期间持续失败则触发关机
|
||
[int]`$MonitorWindowSeconds = 180
|
||
|
||
# 关机倒计时时长(秒)
|
||
[int]`$ShutdownCountdown = 60
|
||
|
||
# 关机倒计时阶段的ping间隔(秒)
|
||
[int]`$CountdownPingInterval = 3
|
||
|
||
# 系统级日志配置
|
||
[string]`$LogDirectory = "$LogPath"
|
||
[string]`$LogFile = Join-Path -Path `$LogDirectory -ChildPath "network_monitor_`$(Get-Date -Format 'yyyyMMdd').log"
|
||
[string]`$ConfigFile = "$DataPath\config.json"
|
||
[int]`$MaxLogDays = 30
|
||
|
||
# 正常连接时的日志记录间隔计数器
|
||
[int]`$normalLogInterval = 24 # 每24次循环记录一次状态 (约6分钟)
|
||
[int]`$normalLogCounter = 0
|
||
|
||
# =================================================
|
||
|
||
# --- 函数定义 ---
|
||
|
||
# 加载配置文件
|
||
function Load-Configuration {
|
||
if (Test-Path -Path `$ConfigFile) {
|
||
try {
|
||
`$config = Get-Content -Path `$ConfigFile | ConvertFrom-Json
|
||
if (`$config.TargetIP) { `$script:TargetIP = `$config.TargetIP }
|
||
if (`$config.MonitorWindowSeconds) { `$script:MonitorWindowSeconds = `$config.MonitorWindowSeconds }
|
||
if (`$config.ShutdownCountdown) { `$script:ShutdownCountdown = `$config.ShutdownCountdown }
|
||
if (`$config.NormalPingInterval) { `$script:NormalPingInterval = `$config.NormalPingInterval }
|
||
Write-Log -Level "INFO" -Message "配置文件加载成功"
|
||
}
|
||
catch {
|
||
Write-Log -Level "WARN" -Message "配置文件格式错误,使用默认配置"
|
||
}
|
||
} else {
|
||
# 创建默认配置文件
|
||
`$defaultConfig = @{
|
||
TargetIP = `$TargetIP
|
||
MonitorWindowSeconds = `$MonitorWindowSeconds
|
||
ShutdownCountdown = `$ShutdownCountdown
|
||
NormalPingInterval = `$NormalPingInterval
|
||
}
|
||
try {
|
||
`$defaultConfig | ConvertTo-Json | Set-Content -Path `$ConfigFile
|
||
Write-Log -Level "INFO" -Message "创建默认配置文件: `$ConfigFile"
|
||
}
|
||
catch {
|
||
Write-Log -Level "WARN" -Message "无法创建配置文件,使用内置默认值"
|
||
}
|
||
}
|
||
}
|
||
|
||
# 日志写入函数
|
||
function Write-Log {
|
||
param(
|
||
[Parameter(Mandatory=`$true)]
|
||
[ValidateSet("INFO", "SUCCESS", "FAIL", "WARN", "CRITICAL", "DEBUG")]
|
||
[string]`$Level,
|
||
|
||
[Parameter(Mandatory=`$true)]
|
||
[string]`$Message
|
||
)
|
||
|
||
`$logTimestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||
`$logEntry = "[`$logTimestamp] [`$Level] `$Message"
|
||
|
||
# 尝试写入日志文件
|
||
try {
|
||
if (-not (Test-Path -Path `$LogDirectory)) {
|
||
New-Item -Path `$LogDirectory -ItemType Directory -ErrorAction Stop | Out-Null
|
||
}
|
||
Add-Content -Path `$LogFile -Value `$logEntry -ErrorAction Stop
|
||
}
|
||
catch {
|
||
# 如果写入失败,尝试输出到事件日志
|
||
try {
|
||
if (-not [System.Diagnostics.EventLog]::SourceExists("SmartNetworkMonitor")) {
|
||
New-EventLog -LogName "Application" -Source "SmartNetworkMonitor"
|
||
}
|
||
Write-EventLog -LogName "Application" -Source "SmartNetworkMonitor" -EventId 1001 -EntryType Information -Message `$logEntry
|
||
}
|
||
catch {
|
||
# 最后尝试输出到控制台(虽然在服务模式下不可见)
|
||
Write-Host "[`$logTimestamp] [CRITICAL] 日志写入失败!`$Message"
|
||
}
|
||
}
|
||
|
||
# 在服务模式下,也输出到事件日志作为备份
|
||
try {
|
||
if (`$Level -eq "CRITICAL" -or `$Level -eq "FAIL") {
|
||
Write-EventLog -LogName "Application" -Source "SmartNetworkMonitor" -EventId 1002 -EntryType Warning -Message `$logEntry -ErrorAction SilentlyContinue
|
||
}
|
||
}
|
||
catch {
|
||
# 忽略事件日志写入错误
|
||
}
|
||
}
|
||
|
||
# 清理旧日志文件
|
||
function Remove-OldLogs {
|
||
try {
|
||
`$cutoffDate = (Get-Date).AddDays(-`$MaxLogDays)
|
||
`$oldLogs = Get-ChildItem -Path `$LogDirectory -Filter "network_monitor_*.log" | Where-Object { `$_.LastWriteTime -lt `$cutoffDate }
|
||
foreach (`$oldLog in `$oldLogs) {
|
||
Remove-Item -Path `$oldLog.FullName -Force
|
||
Write-Log -Level "INFO" -Message "删除旧日志文件: `$(`$oldLog.Name)"
|
||
}
|
||
}
|
||
catch {
|
||
Write-Log -Level "WARN" -Message "清理旧日志文件时出错: `$(`$_.Exception.Message)"
|
||
}
|
||
}
|
||
|
||
# =================================================
|
||
|
||
# --- 主程序开始 ---
|
||
|
||
# 初始化
|
||
Load-Configuration
|
||
Remove-OldLogs
|
||
|
||
# 获取系统信息
|
||
try {
|
||
`$runningAs = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
|
||
`$localIP = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { `$_.InterfaceAlias -notmatch "Loopback" } | Select-Object -First 1).IPAddress
|
||
}
|
||
catch {
|
||
`$runningAs = "Unknown"
|
||
`$localIP = "Unknown"
|
||
}
|
||
|
||
Write-Log -Level "INFO" -Message "========== 系统级网络监控脚本启动 =========="
|
||
Write-Log -Level "INFO" -Message "运行账户: `$runningAs"
|
||
Write-Log -Level "INFO" -Message "本机IP: `$localIP"
|
||
Write-Log -Level "INFO" -Message "监控目标: `$TargetIP"
|
||
Write-Log -Level "INFO" -Message "监控窗口: `${MonitorWindowSeconds}秒"
|
||
Write-Log -Level "INFO" -Message "关机倒计时: `${ShutdownCountdown}秒"
|
||
Write-Log -Level "INFO" -Message "日志目录: `$LogDirectory"
|
||
Write-Log -Level "INFO" -Message "配置文件: `$ConfigFile"
|
||
|
||
# 主循环
|
||
`$failureStartTime = `$null
|
||
|
||
while (`$true) {
|
||
# 测试网络连接
|
||
try {
|
||
`$pingResult = Test-Connection -ComputerName `$TargetIP -Count 1 -Quiet -ErrorAction SilentlyContinue
|
||
`$isOnline = `$pingResult
|
||
}
|
||
catch {
|
||
Write-Log -Level "FAIL" -Message "网络测试出现异常: `$(`$_.Exception.Message)"
|
||
`$isOnline = `$false
|
||
}
|
||
|
||
if (`$isOnline) {
|
||
if (`$failureStartTime) {
|
||
Write-Log -Level "SUCCESS" -Message "网络连接已恢复。"
|
||
`$failureStartTime = `$null
|
||
} else {
|
||
# 减少正常连接时的日志频率
|
||
`$normalLogCounter++
|
||
if (`$normalLogCounter -ge `$normalLogInterval) {
|
||
Write-Log -Level "INFO" -Message "网络连接正常 (定期状态报告)"
|
||
`$normalLogCounter = 0
|
||
}
|
||
}
|
||
|
||
Start-Sleep -Seconds `$NormalPingInterval
|
||
|
||
} else {
|
||
# 网络不通时的处理逻辑
|
||
Write-Log -Level "FAIL" -Message "Ping失败 - 目标: `$TargetIP"
|
||
|
||
if (-not `$failureStartTime) {
|
||
`$failureStartTime = Get-Date
|
||
Write-Log -Level "WARN" -Message "网络首次中断,开始进入监控窗口计时。"
|
||
}
|
||
|
||
`$failureDuration = (New-TimeSpan -Start `$failureStartTime -End (Get-Date)).TotalSeconds
|
||
Write-Log -Level "INFO" -Message "网络已持续中断 `$([math]::Round(`$failureDuration)) / `${MonitorWindowSeconds} 秒。"
|
||
|
||
if (`$failureDuration -ge `$MonitorWindowSeconds) {
|
||
Write-Log -Level "CRITICAL" -Message "网络持续中断已超过 `${MonitorWindowSeconds} 秒,开始关机流程。"
|
||
|
||
`$shutdownCancelled = `$false
|
||
`$countdownEndTime = (Get-Date).AddSeconds(`$ShutdownCountdown)
|
||
|
||
while ((Get-Date) -lt `$countdownEndTime -and -not `$shutdownCancelled) {
|
||
`$remainingSeconds = [math]::Ceiling((`$countdownEndTime - (Get-Date)).TotalSeconds)
|
||
if (`$remainingSeconds -le 0) { break }
|
||
|
||
Write-Log -Level "WARN" -Message "距离关机还有 `$remainingSeconds 秒... 正在快速检测网络。"
|
||
|
||
# 在倒计时中再次检测网络
|
||
try {
|
||
if (Test-Connection -ComputerName `$TargetIP -Count 1 -Quiet -ErrorAction SilentlyContinue) {
|
||
Write-Log -Level "SUCCESS" -Message "网络在倒计时期间恢复!取消关机。"
|
||
`$failureStartTime = `$null
|
||
`$shutdownCancelled = `$true
|
||
break
|
||
}
|
||
}
|
||
catch {
|
||
Write-Log -Level "WARN" -Message "倒计时期间网络测试出现异常: `$(`$_.Exception.Message)"
|
||
}
|
||
|
||
Start-Sleep -Seconds `$CountdownPingInterval
|
||
}
|
||
|
||
if (-not `$shutdownCancelled) {
|
||
Write-Log -Level "CRITICAL" -Message "关机倒计时完成,执行系统关机命令。"
|
||
try {
|
||
# 执行实际关机命令
|
||
Stop-Computer -Force
|
||
Write-Log -Level "CRITICAL" -Message "关机命令已执行。"
|
||
}
|
||
catch {
|
||
Write-Log -Level "CRITICAL" -Message "关机命令执行失败: `$(`$_.Exception.Message)"
|
||
}
|
||
exit
|
||
}
|
||
} else {
|
||
Start-Sleep -Seconds `$NormalPingInterval
|
||
}
|
||
}
|
||
}
|
||
"@
|
||
|
||
# 写入系统版本脚本
|
||
$SystemScriptPath = Join-Path $ProgramPath "smart_shutdown_system.ps1"
|
||
try {
|
||
$SystemScriptContent | Set-Content -Path $SystemScriptPath -Encoding UTF8
|
||
Write-Host "[OK] 创建系统脚本: $SystemScriptPath" -ForegroundColor Green
|
||
}
|
||
catch {
|
||
Write-Error "创建系统脚本失败: $($_.Exception.Message)"
|
||
exit 1
|
||
}
|
||
|
||
# 创建默认配置文件
|
||
Write-Host "正在创建配置文件..." -ForegroundColor Yellow
|
||
|
||
$DefaultConfig = @{
|
||
TargetIP = "192.168.3.3"
|
||
MonitorWindowSeconds = 180
|
||
ShutdownCountdown = 60
|
||
NormalPingInterval = 15
|
||
}
|
||
|
||
$ConfigPath = Join-Path $DataPath "config.json"
|
||
try {
|
||
$DefaultConfig | ConvertTo-Json -Depth 10 | Set-Content -Path $ConfigPath -Encoding UTF8
|
||
Write-Host "[OK] 创建配置文件: $ConfigPath" -ForegroundColor Green
|
||
}
|
||
catch {
|
||
Write-Error "创建配置文件失败: $($_.Exception.Message)"
|
||
exit 1
|
||
}
|
||
|
||
# 配置任务计划程序
|
||
Write-Host "正在配置任务计划程序..." -ForegroundColor Yellow
|
||
|
||
try {
|
||
# 删除已存在的任务(如果有)
|
||
try {
|
||
Unregister-ScheduledTask -TaskName "Smart Network Shutdown Monitor" -Confirm:$false -ErrorAction SilentlyContinue
|
||
}
|
||
catch {
|
||
# 忽略错误,任务可能不存在
|
||
}
|
||
|
||
# 创建触发器(系统启动时)
|
||
$Trigger = New-ScheduledTaskTrigger -AtStartup
|
||
|
||
# 创建操作
|
||
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-WindowStyle Hidden -ExecutionPolicy Bypass -File `"$SystemScriptPath`""
|
||
|
||
# 创建设置
|
||
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -DontStopOnIdleEnd -ExecutionTimeLimit (New-TimeSpan -Days 365)
|
||
|
||
# 创建主体(以SYSTEM身份运行)
|
||
$Principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
|
||
|
||
# 注册任务
|
||
Register-ScheduledTask -TaskName "Smart Network Shutdown Monitor" -Trigger $Trigger -Action $Action -Settings $Settings -Principal $Principal -Description "智能网络监控脚本 - 系统级运行"
|
||
|
||
Write-Host "[OK] 任务计划程序配置完成" -ForegroundColor Green
|
||
}
|
||
catch {
|
||
Write-Error "配置任务计划程序失败: $($_.Exception.Message)"
|
||
exit 1
|
||
}
|
||
|
||
# 创建管理脚本
|
||
Write-Host "正在创建管理工具..." -ForegroundColor Yellow
|
||
|
||
$ManagementScript = @"
|
||
# 智能网络监控脚本 - 管理工具
|
||
|
||
Write-Host "智能网络监控脚本 - 管理工具" -ForegroundColor Cyan
|
||
Write-Host "==============================" -ForegroundColor Cyan
|
||
Write-Host ""
|
||
|
||
Write-Host "可用操作:" -ForegroundColor Yellow
|
||
Write-Host "1. 查看任务状态"
|
||
Write-Host "2. 启动监控任务"
|
||
Write-Host "3. 停止监控任务"
|
||
Write-Host "4. 查看今天的日志"
|
||
Write-Host "5. 查看实时日志"
|
||
Write-Host "6. 查看配置文件"
|
||
Write-Host "7. 编辑配置文件"
|
||
Write-Host ""
|
||
|
||
`$choice = Read-Host "请选择操作 (1-7)"
|
||
|
||
switch (`$choice) {
|
||
"1" {
|
||
Get-ScheduledTask -TaskName "Smart Network Shutdown Monitor" | Format-Table
|
||
}
|
||
"2" {
|
||
Start-ScheduledTask -TaskName "Smart Network Shutdown Monitor"
|
||
Write-Host "任务已启动" -ForegroundColor Green
|
||
}
|
||
"3" {
|
||
Stop-ScheduledTask -TaskName "Smart Network Shutdown Monitor"
|
||
Write-Host "任务已停止" -ForegroundColor Green
|
||
}
|
||
"4" {
|
||
`$logFile = "$LogPath\network_monitor_`$(Get-Date -Format 'yyyyMMdd').log"
|
||
if (Test-Path `$logFile) {
|
||
Get-Content `$logFile
|
||
} else {
|
||
Write-Host "今天的日志文件不存在" -ForegroundColor Red
|
||
}
|
||
}
|
||
"5" {
|
||
`$logFile = "$LogPath\network_monitor_`$(Get-Date -Format 'yyyyMMdd').log"
|
||
if (Test-Path `$logFile) {
|
||
Get-Content `$logFile -Wait
|
||
} else {
|
||
Write-Host "今天的日志文件不存在" -ForegroundColor Red
|
||
}
|
||
}
|
||
"6" {
|
||
Get-Content "$DataPath\config.json"
|
||
}
|
||
"7" {
|
||
notepad "$DataPath\config.json"
|
||
}
|
||
default {
|
||
Write-Host "无效选择" -ForegroundColor Red
|
||
}
|
||
}
|
||
|
||
Write-Host ""
|
||
Write-Host "常用命令:" -ForegroundColor Yellow
|
||
Write-Host "1. 查看任务状态:"
|
||
Write-Host " Get-ScheduledTask -TaskName 'Smart Network Shutdown Monitor'"
|
||
Write-Host ""
|
||
Write-Host "2. 启动任务:"
|
||
Write-Host " Start-ScheduledTask -TaskName 'Smart Network Shutdown Monitor'"
|
||
Write-Host ""
|
||
Write-Host "3. 停止任务:"
|
||
Write-Host " Stop-ScheduledTask -TaskName 'Smart Network Shutdown Monitor'"
|
||
Write-Host ""
|
||
Write-Host "4. 查看今天日志:"
|
||
Write-Host " Get-Content '$LogPath\network_monitor_`$(Get-Date -Format 'yyyyMMdd').log'"
|
||
Write-Host ""
|
||
Write-Host "5. 实时查看日志:"
|
||
Write-Host " Get-Content '$LogPath\network_monitor_`$(Get-Date -Format 'yyyyMMdd').log' -Wait"
|
||
Write-Host ""
|
||
Write-Host "6. 查看配置:"
|
||
Write-Host " Get-Content '$DataPath\config.json'"
|
||
Write-Host ""
|
||
Write-Host "7. 编辑配置文件:"
|
||
Write-Host " notepad '$DataPath\config.json'"
|
||
Write-Host ""
|
||
"@
|
||
|
||
$ManagementScriptPath = Join-Path $ProgramPath "manage.ps1"
|
||
try {
|
||
$ManagementScript | Set-Content -Path $ManagementScriptPath -Encoding UTF8
|
||
Write-Host "[OK] 创建管理脚本: $ManagementScriptPath" -ForegroundColor Green
|
||
}
|
||
catch {
|
||
Write-Error "创建管理脚本失败: $($_.Exception.Message)"
|
||
exit 1
|
||
}
|
||
|
||
Write-Host ""
|
||
Write-Host "[INFO] 系统级部署完成!" -ForegroundColor Green
|
||
Write-Host ""
|
||
Write-Host "部署摘要:" -ForegroundColor Cyan
|
||
Write-Host "[OK] 程序文件已部署到: $ProgramPath" -ForegroundColor White
|
||
Write-Host "[OK] 数据目录已创建: $DataPath" -ForegroundColor White
|
||
Write-Host "[OK] 日志目录已创建: $LogPath" -ForegroundColor White
|
||
Write-Host "[OK] 任务计划程序已配置(系统启动时运行)" -ForegroundColor White
|
||
Write-Host "[OK] SYSTEM 权限配置完成" -ForegroundColor White
|
||
Write-Host ""
|
||
Write-Host "管理工具:" -ForegroundColor Yellow
|
||
Write-Host "- 管理脚本: $ManagementScriptPath" -ForegroundColor White
|
||
Write-Host "- 配置文件: $DataPath\config.json" -ForegroundColor White
|
||
Write-Host "- 今天日志: $LogPath\network_monitor_$(Get-Date -Format 'yyyyMMdd').log" -ForegroundColor White
|
||
Write-Host ""
|
||
Write-Host "下次重启后,脚本将自动运行!" -ForegroundColor Green
|
||
Write-Host ""
|
||
|
||
# 询问是否立即启动
|
||
$response = Read-Host "是否立即启动监控任务?(Y/N)"
|
||
if ($response -eq 'Y' -or $response -eq 'y' -or $response -eq '') {
|
||
try {
|
||
Start-ScheduledTask -TaskName "Smart Network Shutdown Monitor"
|
||
Write-Host "[OK] 监控任务已启动" -ForegroundColor Green
|
||
}
|
||
catch {
|
||
Write-Host "[X] 启动任务失败: $($_.Exception.Message)" -ForegroundColor Red
|
||
}
|
||
}
|