Windows 服务器巡检
本文详细介绍如何利用 PowerShell 采集 Windows 环境、资源使用率、服务进程、event日志、安全配置等信息,以便作为巡检报告或健康诊断的参考依据。
巡检脚本
- 由于篇幅问题,本文仅展示 scripts 目录下的部分指标脚本,更多请 联系我们
wins_check.ps1
- 主巡检文件:wins_check.ps1
注1:请根据需要调整参数:$portList(需要监控的端口清单)、$serviceList(需要监控的服务清单)
注2:如下脚本已兼容测试:Windows 10/2012+、PowerShell 4.0+
# Windows巡检,支持 Windows 10/2012+
$host.ui.RawUI.WindowTitle = "Windows巡检.v20260425.余"
# 加载所有脚本
$modulePath = Join-Path $PSScriptRoot "scripts"
Get-ChildItem "$modulePath/*.ps1" -Recurse | ForEach-Object { . $_.FullName }
# 创建日志目录
$localpath = ".\logs"
$localip = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -notlike 'Loopback*' -and $_.InterfaceAlias -notlike '*vEthernet*'}).IPAddress | Select-Object -First 1
if (-not $localip) { $localip = "127.0.0.1" }
$logDir = "$localpath\$localip"
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory $logDir -Force | Out-Null }
# 配置检查清单
$portList = @(80,443,1433,3389,10000)
$serviceList = @("W32Time","wuauserv","BITS","EventLog","WinDefend","W3SVC","MSSQLSERVER","SQLSERVERAGENT","OSearch16","SPSearchHostController","SPAdminV4","SPTimerV4","SPTraceV4","WACSM")
# 导出CSV格式
function Export-CheckData {
param($Data, $Path)
if ($Data) { $Data | Export-Csv $Path -Encoding UTF8 -NoTypeInformation -Force }
}
# 巡检开始
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host " 主机: $env:COMPUTERNAME ($localip)" -ForegroundColor Cyan
Write-Host " 时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "[01/12] 开始采集 System 信息..." -ForegroundColor Green
Export-CheckData (Get-SystemInfo) (Join-Path $logDir "1.system_info.csv")
Write-Host "[02/12] 开始采集 CPU 信息..." -ForegroundColor Green
Export-CheckData (Get-CPUInfo) (Join-Path $logDir "2.cpu_info.csv")
Write-Host "[03/12] 开始采集 Disk 信息..." -ForegroundColor Green
Export-CheckData (Get-DiskInfo) (Join-Path $logDir "3.disk_info.csv")
Write-Host "[04/12] 开始采集 Network 信息..." -ForegroundColor Green
#Export-CheckData (Get-NetworkInfo) (Join-Path $logDir "4.network_info.csv")
Write-Host "[05/12] 开始采集 Windows 日志..." -ForegroundColor Green
Export-CheckData (Get-LogWindowsEvents) (Join-Path $logDir "5.log_windows_events.csv")
Write-Host "[06/12] 开始采集 服务 状态..." -ForegroundColor Green
Export-CheckData (Get-ServiceInfo -ServiceNames $serviceList) (Join-Path $logDir "6.service_info.csv")
Write-Host "[07/12] 开始采集 端口连接 信息..." -ForegroundColor Green
#Export-CheckData (Get-PortConnection -Ports $portList) (Join-Path $logDir "7.port_connection.csv")
Write-Host "[08/12] 开始采集 进程 信息..." -ForegroundColor Green
#Export-CheckData (Get-TopProcesses) (Join-Path $logDir "8.top_processes.csv")
Write-Host "[09/12] 开始采集 软件 信息..." -ForegroundColor Green
#Export-CheckData (Get-InstalledProducts) (Join-Path $logDir "9.install_products.csv")
Write-Host "[10/12] 开始采集 安全 信息..." -ForegroundColor Green
#Export-CheckData (Get-SecurityInfo) (Join-Path $logDir "10.security_info.csv")
Write-Host "[11/12] 开始采集 HotFix 日志..." -ForegroundColor Green
#Export-CheckData (Get-HotFixInfo) (Join-Path $logDir "11.hot_fix.csv")
Write-Host "[12/12] 开始采集 https 页面信息..." -ForegroundColor Green
#Export-CheckData (Get-HttpURLInfo) (Join-Path $logDir "12.http_url_info.csv")
#Export-CheckData (Get-HttpsURLInfo) (Join-Path $logDir "13.https_url_info.csv")
Start-Sleep -Seconds 5
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "巡检执行完毕!`n" -ForegroundColor Green
scripts\SystemInfo.ps1
- 采集 System 信息的脚本:scripts\SystemInfo.ps1
function Get-SystemInfo {
try {
$os = Get-WmiObject -Class Win32_OperatingSystem -ErrorAction Stop
$build = (Get-ItemProperty "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion").CurrentBuild
$ubr = (Get-ItemProperty "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion").UBR
$winver = "$build.$ubr"
$sysinfo = Get-WmiObject win32_computersystem
$timezone = ((Get-WmiObject -Class win32_timezone).Caption -split '[()]')[1]
$bios = Get-WmiObject -Class win32_bios
$original = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name 'portnumber'
$latestUpdate = Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 1
return [PSCustomObject]@{
HostName = $sysinfo.DNSHostName
Domain = $sysinfo.Domain
OperatingSystem = $os.Caption.Replace("Microsoft ","")
Arch = $os.OSArchitecture
WinVersion = $os.version
UBRevision = $winver
InstallDate = $os.ConvertToDateTime($os.InstallDate)
LastUpdate = $latestUpdate.InstalledOn
LastUpdateKB = $latestUpdate.HotFixID
LastBootUp = $os.ConvertToDateTime($os.LastBootUpTime)
UpDays = ((Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime).Days
TimeZone = $timezone
SystemType = $sysinfo.SystemType
Manufacturer = $bios.Manufacturer
Model = $sysinfo.Model
BIOSName = $bios.Name
SerialNumber = $bios.SerialNumber
RDPPort = $original.PortNumber
PSVersion = $PSVersionTable.PSVersion
}
}
catch {
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}
scripts\CPUInfo.ps1
- 采集 CPU 信息的脚本:scripts\CPUInfo.ps1
function Get-CPUInfo {
try {
$cpu = Get-WmiObject -Class Win32_Processor -ErrorAction Stop | Select-Object -First 1
$cpuCount = Get-CimInstance -ClassName Win32_Processor | Measure-Object | Select-Object -ExpandProperty Count
$numOfCore = (Get-WmiObject -Class Win32_Processor).NumberOfCores
$coreCount = (Get-CimInstance -ClassName Win32_Processor).NumberOfLogicalProcessors | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$memory = Get-WmiObject -Class Win32_ComputerSystem -ErrorAction Stop
$totalMemGB = [math]::Round($memory.TotalPhysicalMemory / 1GB, 2)
$os = Get-WmiObject -Class Win32_OperatingSystem -ErrorAction Stop
$freeMemGB = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
$usedMemGB = [math]::Round($totalMemGB - $freeMemGB, 2)
# 2次采集间隔5秒,避免瞬时指标不准确
$cpuAvg1 = (Get-Counter -Counter "\Processor(_Total)\% Processor Time").CounterSamples[0].CookedValue
Start-Sleep -Seconds 3
$cpuAvg2 = (Get-Counter -Counter "\Processor(_Total)\% Processor Time").CounterSamples[0].CookedValue
$cpuAvg = [math]::Round(($cpuAvg1 + $cpuAvg2) / 2, 2)
$DiskQueue = Get-Counter -Counter "\PhysicalDisk(_Total)\Current Disk Queue Length" -ErrorAction Stop
$DiskQueueLength = [math]::Round($DiskQueue.CounterSamples.CookedValue, 2)
return [PSCustomObject]@{
CPU = $cpu.Name
Counts = $cpuCount
LogicalCores = $coreCount
CPU_Usage_Pct = $cpuAvg
Mem_Total_GB = $totalMemGB
Mem_Used_GB = $usedMemGB
Mem_Free_GB = $freeMemGB
Mem_Usage_Pct = [math]::Round(($usedMemGB / $totalMemGB) * 100, 2)
DiskQueueLength = $DiskQueueLength
}
}
catch {
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}
scripts\DiskInfo.ps1
- 采集 Disk 信息的脚本:scripts\DiskInfo.ps1
function Get-DiskInfo {
try {
$disks = Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" -ErrorAction Stop
return $disks | ForEach-Object {
[PSCustomObject]@{
DriveID = $_.DeviceID
DriveType = $_.FileSystem
Total_GB = [math]::Round($_.Size / 1GB, 2)
Used_GB = [math]::Round(($_.Size - $_.FreeSpace) / 1GB, 2)
Free_GB = [math]::Round($_.FreeSpace / 1GB, 2)
Usage_Pct = [math]::Round((($_.Size - $_.FreeSpace) / $_.Size) * 100, 2)
}
}
}
catch {
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}
scripts\LogWindowsEvents.ps1
- 采集 event事件日志 信息的脚本:scripts\LogWindowsEvents.ps1
function Get-LogWindowsEvents {
$endTime = Get-Date
$startTime = $endTime.AddDays(-7) #.最近7天
# 1.处理 Application 和 System 日志
$logNames = "Application", "System"
$result = [PSCustomObject]@{
login_succ_count = 0
login_fail_count = 0
login_cred_count = 0
login_spec_count = 0
app_warn_count = 0
app_errr_count = 0
sys_warn_count = 0
sys_errr_count = 0
tot_warn_count = 0
tot_errr_count = 0
check_time = $endTime
}
foreach ($logName in $logNames) {
try {
# PowerShell 4.0 兼容方式:使用 Get-WinEvent
$events = Get-WinEvent -LogName $logName -ErrorAction Stop | Where-Object {
$_.TimeCreated -ge $startTime -and $_.TimeCreated -le $endTime
}
foreach ($event in $events) {
# Windows 标准级别:2=错误, 3=警告
$level = $event.Level
if ($level -eq 2) {
if ($logName -eq "Application") { $result.app_errr_count++ }
if ($logName -eq "System") { $result.sys_errr_count++ }
}
elseif ($level -eq 3) {
if ($logName -eq "Application") { $result.app_warn_count++ }
if ($logName -eq "System") { $result.sys_warn_count++ }
}
}
}
catch {
Write-Host "Error reading $logName : $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}
$result.tot_errr_count = $result.app_errr_count + $result.sys_errr_count
$result.tot_warn_count = $result.app_warn_count + $result.sys_warn_count
# 2.处理 Security 日志, 4624/4625/4648/4672 对应 登录成功/登录失败/使用显式凭据登录/特殊权限登录
try {
$targetEventIds = 4624, 4625, 4648, 4672
$events = Get-WinEvent -FilterHashtable @{
LogName = "Security"
Id = $targetEventIds
StartTime = $startTime
EndTime = $endTime
} -ErrorAction SilentlyContinue
if ($events) {
foreach ($event in $events) {
switch ($event.Id) {
4624 { $result.login_succ_count++ }
4625 { $result.login_fail_count++ }
4648 { $result.login_cred_count++ }
4672 { $result.login_spec_count++ }
}
}
}
}
catch {
Write-Host "Error reading Security log: $($_.Exception.Message)" -ForegroundColor Red
}
return $result
}
scripts\ServiceInfo.ps1
- 采集 Service 信息的脚本:scripts\ServiceInfo.ps1
function Get-ServiceInfo {
param([string[]]$ServiceNames)
try {
$result = @()
foreach ($svcName in $ServiceNames) {
$svc = Get-Service -Name $svcName -ErrorAction SilentlyContinue
if ($svc) {
$result += [PSCustomObject]@{
ServiceName = $svc.Name
DisplayName = $svc.DisplayName
Status = $svc.Status
StartType = $svc.StartType
}
}
}
return $result
}
catch {
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}
如何使用
- 第1步,目录结构参考如下:
C:\Windows\System32>cd /d c:\windows_check
c:\windows_check>tree /F
文件夹 PATH 列表
卷序列号为 3E68-D7B4
C:.
│ wins_check.ps1 #.主巡检文件
│
└─ scripts
CPUInfo.ps1 #.采集 CPU 信息
DiskInfo.ps1 #.采集 Disk 信息
HotFixInfo.ps1 #.采集 HotFix 信息
HttpsURLInfo.ps1 #.采集 https域名 信息
HttpURLInfo.ps1 #.采集 http域名 信息
InstalledProducts.ps1 #.采集 软件 信息
LogWindowsEvents.ps1 #.采集 Windows日志 信息
NetworkInfo.ps1 #.采集 Network 信息
PortConnection.ps1 #.采集 端口连接 信息
SecurityInfo.ps1 #.采集 安全 信息
ServiceInfo.ps1 #.采集 服务 信息
SystemInfo.ps1 #.采集 System 信息
TopProcesses.ps1 #.采集 进程 信息
- 第2步,以管理员身份运行 PowerShell,然后输入 .\wins_check.ps1 即可(会自动创建 logs 存放采集到的日志文件),过程如下:
- 第3步,由于日志文件为 csv 格式,所以可以直接用 excel 打开,效果如下:

