前面幾天,我們已經把單台 Windows Server 的巡檢內容慢慢補齊。
目前可以檢查:
CPU
Memory
Disk
Service
Uptime
Event Log
如果今天只有一台 Server,其實已經很好用了。
但真正的企業環境,很少只有:
SERVER01
更常見的是:
SERVER01
SERVER02
SERVER03
SERVER04
SERVER05
...
甚至幾十台、幾百台。
這時如果我們還是:
RDP SERVER01
↓
執行 PowerShell
RDP SERVER02
↓
再執行一次
RDP SERVER03
↓
再執行一次
那其實只是把原本的人工巡檢,換成「人工執行 Script」。
還不能算真正的自動化。
所以 Day 10 要處理一個很重要的問題:
能不能在一台管理電腦上,直接取得其他 Windows Server 的資料?
答案就是:
PowerShell Remoting
今天主要會碰到:
Test-WSMan
Invoke-Command
New-PSSession
Get-PSSession
Remove-PSSession
最終我們希望做到:
Management Server
│
├── SERVER01
├── SERVER02
├── SERVER03
└── SERVER04
↓
PowerShell Remoting
↓
收集巡檢資料
↓
統一報表
PowerShell Remoting 是什麼?
可以先把它理解成:
從目前這台電腦,遠端執行另一台 Windows 電腦上的 PowerShell 指令。
例如平常我們在 SERVER01 上執行:
Get-Service
只能取得 SERVER01 的 Service。
如果使用 PowerShell Remoting:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
Get-Service
}
就可以從管理端直接要求:
SERVER01,請幫我執行 Get-Service,再把結果傳回來。
這樣就不需要先 RDP 進 Server。
PowerShell Remoting 背後是什麼?
Windows PowerShell Remoting 常見會透過:
WinRM
Windows Remote Management
處理遠端管理。
概念大概是:
PowerShell
↓
WinRM
↓
Network
↓
Remote Windows Server
↓
執行 Command
↓
回傳 Object
常見 WinRM Port:
HTTP 5985
HTTPS 5986
這裡要注意:
5985 使用 HTTP,不代表驗證資訊就一定是明文直接在網路上傳送。
在網域環境中,PowerShell Remoting 通常會搭配 Kerberos 等 Windows 驗證機制。
今天先專注在操作,不深入 WinRM 驗證架構。
第一件事:確認 WinRM 能不能連
PowerShell 提供:
Test-WSMan
例如:
Test-WSMan SERVER01
如果正常,可能看到類似:
wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor : Microsoft Corporation
ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0
代表:
SERVER01 的 WinRM 可以回應。
如果無法連線,可能會看到:
WinRM cannot complete the operation...
這時候就要開始排查。
PowerShell Remoting 不通時,先不要一直改設定
我會先按照順序確認:
① DNS
② Network
③ Port
④ WinRM Service
⑤ Firewall
⑥ Authentication
⑦ Permission
例如先:
Resolve-DnsName SERVER01
確認 DNS。
再:
Test-Connection SERVER01 -Count 1
接著確認 WinRM Port:
Test-NetConnection -ComputerName SERVER01
-Port 5985
可能看到:
ComputerName : SERVER01
RemotePort : 5985
TcpTestSucceeded : True
這樣排查會比一開始就亂改 Firewall 或 TrustedHosts 安全很多。
Remote Server 必須支援 Remoting
如果是在允許進行遠端管理的測試或管理環境,可在目標 Windows 主機上以系統管理員權限確認 PowerShell Remoting 設定。
常見指令是:
Enable-PSRemoting
它會協助設定:
WinRM Service
Listener
Firewall Rule
PowerShell Remoting
在很多 Windows Server 環境裡,WinRM 可能已經由系統設定或 Group Policy 管理。
所以企業環境裡不要看到不通就直接:
Enable-PSRemoting -Force
最好先確認:
這台 Server 的 WinRM 是不是由公司的 GPO 或資安政策統一管理?
這也是維運上很重要的習慣。
第一個 Invoke-Command
假設:
Test-WSMan SERVER01
正常。
就可以試:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
hostname
}
可能回:
SERVER01
這表示我們已經成功做到:
從本機讓 SERVER01 執行指令。
ScriptBlock 是什麼?
這裡第一次看到:
-ScriptBlock {
...
}
可以先把它理解成:
我要交給遠端 Server 執行的 PowerShell 程式。
例如:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
Get-Service
}
這裡:
Get-Service
不是在本機執行。
而是在:
SERVER01
執行。
這個觀念非常重要。
確認到底在哪一台機器執行
可以做個簡單測試:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
$env:COMPUTERNAME
}
結果:
SERVER01
如果本機叫:
ADMIN-PC
但結果是:
SERVER01
就可以確認 ScriptBlock 的內容確實是在 Remote Server 執行。
取得遠端 Service
例如:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
Get-Service W32Time
}
可能得到:
Status Name DisplayName PSComputerName
Running W32Time Windows Time SERVER01
這裡可能會多看到一個很重要的欄位:
PSComputerName
PowerShell Remoting 會幫我們保留:
這筆資料到底來自哪台電腦。
這對批次巡檢非常有用。
那 CPU、Memory 也可以嗎?
當然可以。
例如 CPU:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
Get-CimInstance Win32_Processor |
Select-Object Name, LoadPercentage
}
Memory:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
Get-CimInstance Win32_OperatingSystem |
Select-Object `
TotalVisibleMemorySize,
FreePhysicalMemory
}
Disk:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
Get-CimInstance Win32_LogicalDisk `
-Filter "DriveType=3"
}
有沒有發現?
Day 7、Day 8 學的東西幾乎不用重學。
只是從:
Local
變成:
Remote
真正有趣的是:ComputerName 可以放很多台
假設現在有:
$Servers = @(
"SERVER01"
"SERVER02"
"SERVER03"
)
可以直接:
Invoke-Command -ComputerName $Servers
-ScriptBlock {
$env:COMPUTERNAME
}
可能得到:
SERVER01
SERVER02
SERVER03
也就是說:
Invoke-Command 本身就可以對多台電腦執行。
這才是 Day 10 真正重要的地方。
一次取得多台 Server 的 Uptime
例如:
$Servers = @(
"SERVER01"
"SERVER02"
"SERVER03"
)
Invoke-Command -ComputerName $Servers
-ScriptBlock {
$OS = Get-CimInstance Win32_OperatingSystem
$Uptime = (Get-Date) - $OS.LastBootUpTime
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
LastBootTime = $OS.LastBootUpTime
UptimeDays = [math]::Round(
$Uptime.TotalDays,
1
)
}
}
結果可能:
ComputerName LastBootTime UptimeDays
SERVER01 2026/09/05 03:12 13.1
SERVER02 2026/08/20 01:35 29.2
SERVER03 2026/09/17 02:10 1.2
以前需要 RDP 三台。
現在一條流程就處理完了。
開始把 CPU、Memory、Uptime 放在一起
我們來做第一個遠端 Health Check。
$Servers = @(
"SERVER01"
"SERVER02"
"SERVER03"
)
$Results = Invoke-Command -ComputerName $Servers
-ScriptBlock {
# CPU
$CPUUsage = [math]::Round(
(
Get-CimInstance Win32_Processor |
Measure-Object `
-Property LoadPercentage `
-Average
).Average,
2
)
# Memory
$OS = Get-CimInstance Win32_OperatingSystem
$TotalMemory = $OS.TotalVisibleMemorySize
$FreeMemory = $OS.FreePhysicalMemory
$MemoryUsage = [math]::Round(
(
($TotalMemory - $FreeMemory) /
$TotalMemory
) * 100,
2
)
# Uptime
$Uptime = (Get-Date) - $OS.LastBootUpTime
# Output
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
CPUUsage = $CPUUsage
MemoryUsage = $MemoryUsage
UptimeDays = [math]::Round(
$Uptime.TotalDays,
1
)
CheckTime = Get-Date
}
}
最後:
$Results
可能看到:
ComputerName CPUUsage MemoryUsage UptimeDays
SERVER01 18 62.3 13.1
SERVER02 43 78.1 29.2
SERVER03 10 51.7 1.2
這就是第一個:
Multi-Server Health Check
這時候其實已經跨了一大步
Day 7 的架構是:
SERVER01
↓
PowerShell
↓
Health Check
Day 10 已經變成:
ADMIN-PC
│
PowerShell Remoting
│
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
SERVER01 SERVER02 SERVER03
│ │ │
└─────────┼─────────┘
▼
Results
↓
CSV Report
這開始比較像真正的企業維運工具。
把結果輸出 CSV
前面已經很熟了:
$ReportFolder = "C:\Temp"
if (-not (Test-Path $ReportFolder)) {
New-Item `
-Path $ReportFolder `
-ItemType Directory |
Out-Null
}
$Date = Get-Date -Format "yyyyMMdd"
接著:
$Results |
Select-Object ComputerName, CPUUsage, MemoryUsage, UptimeDays, CheckTime | Export-Csv
-Path "$ReportFolder\Server_Health_$Date.csv" -NoTypeInformation
-Encoding UTF8
最後:
C:\Temp\Server_Health_20260918.csv
例如:
ComputerName CPUUsage MemoryUsage UptimeDays
SERVER01 18 62.3 13.1
SERVER02 43 78.1 29.2
SERVER03 10 51.7 1.2
現在工程師只需要打開一份報表。
而不是登入三台 Server。
但如果其中一台 Server 連不上呢?
這就是實際環境一定會碰到的問題。
假設:
SERVER01 → OK
SERVER02 → WinRM 不通
SERVER03 → OK
我們不希望:
SERVER02 出錯
↓
整批巡檢亂掉
Day 6 學的:
try
catch
現在又派上用場了。
我比較喜歡先逐台確認
雖然:
Invoke-Command -ComputerName $Servers
可以一次處理多台,
但寫第一版維運工具時,我反而會使用:
foreach
因為比較容易清楚記錄:
哪台成功
哪台失敗
失敗原因
例如:
$Servers = @(
"SERVER01"
"SERVER02"
"SERVER03"
)
$Results = @()
foreach ($Server in $Servers) {
try {
Test-WSMan `
-ComputerName $Server `
-ErrorAction Stop |
Out-Null
$Result = Invoke-Command `
-ComputerName $Server `
-ErrorAction Stop `
-ScriptBlock {
$OS = Get-CimInstance Win32_OperatingSystem
$CPUUsage = [math]::Round(
(
Get-CimInstance Win32_Processor |
Measure-Object `
-Property LoadPercentage `
-Average
).Average,
2
)
$MemoryUsage = [math]::Round(
(
(
$OS.TotalVisibleMemorySize -
$OS.FreePhysicalMemory
) /
$OS.TotalVisibleMemorySize
) * 100,
2
)
$Uptime = (Get-Date) - $OS.LastBootUpTime
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
Connection = "Success"
CPUUsage = $CPUUsage
MemoryUsage = $MemoryUsage
UptimeDays = [math]::Round(
$Uptime.TotalDays,
1
)
ErrorMessage = ""
CheckTime = Get-Date
}
}
$Results += $Result
}
catch {
$Results += [PSCustomObject]@{
ComputerName = $Server
Connection = "Failed"
CPUUsage = $null
MemoryUsage = $null
UptimeDays = $null
ErrorMessage = $_.Exception.Message
CheckTime = Get-Date
}
}
}
這樣 SERVER02 就算出問題:
SERVER01 Success
SERVER02 Failed
SERVER03 Success
SERVER03 還是可以繼續執行。
報表現在會更有意義
可能變成:
Server Connection CPU Memory Uptime Error
SERVER01 Success 18% 62% 13d
SERVER02 Failed WinRM connection failed
SERVER03 Success 10% 52% 1d
這時候看到:
SERVER02 = Failed
就知道要處理的是:
Remote Management / Connection
而不是誤判:
SERVER02 CPU、Memory 都沒有資料,所以 Server 壞了。
這種狀態分類很重要。
Ping 跟 WinRM 要分開
可以 Ping:
True
並不代表:
WinRM 可以用
例如:
SERVER01
Ping → OK
Port 5985 → Failed
那問題比較可能落在:
WinRM
Firewall
GPO
Listener
Authentication
反過來:
Ping → Failed
也不能百分之百直接說 Server Down。
因為可能單純:
ICMP 被 Firewall 擋掉
所以到了 Day 10,我們可以把 Connectivity 再細分:
DNS
ICMP
WinRM
而不是只有一個:
Online / Offline
用 Test-NetConnection 檢查 WinRM Port
如果:
Test-WSMan SERVER01
失敗,可以再:
Test-NetConnection -ComputerName SERVER01
-Port 5985
例如:
TcpTestSucceeded : False
這時可以往:
Firewall
WinRM Listener
Network ACL
Service
方向找。
如果:
TcpTestSucceeded : True
但:
Test-WSMan
還是不行,
則可能比較偏:
Authentication
Permission
WinRM Configuration
這就是系統工程師很重要的一個思考方式:
不要只知道「連不上」,要繼續把問題縮小。
網域環境會比較單純
如果:
ADMIN-PC
SERVER01
SERVER02
全部都:
同一個 Active Directory Domain
而且使用者本身有適當的管理權限,
PowerShell Remoting 通常會比較容易處理。
例如:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
hostname
}
Windows 可以透過網域驗證機制處理身分認證。
非 Domain 環境會比較麻煩
如果是:
Workgroup
或者:
不同 Domain
沒有 Trust
Remoting 設定會複雜一些。
網路上常常會看到:
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*"
但我不建議一開始就照抄 *。
因為:
TrustedHosts = *
等於把信任範圍放得非常大。
比較合理的方式是:
先確認環境
↓
確認為什麼不能用 Kerberos
↓
限制 TrustedHosts 範圍
↓
再決定驗證方式
企業環境則應該優先遵循既有的 WinRM / GPO / 資安政策。
New-PSSession 又是什麼?
目前我們一直使用:
Invoke-Command
這種方式很適合:
執行一次工作 → 拿結果 → 結束。
例如:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
Get-Service
}
但有時候我們會對同一台 Server 做很多操作。
這時候可以建立:
New-PSSession
例如:
$Session = New-PSSession `
-ComputerName SERVER01
確認:
Get-PSSession
可能看到:
Id Name ComputerName State Availability
1 WinRM1 SERVER01 Open Available
使用現有 Session
例如:
Invoke-Command -Session $Session
-ScriptBlock {
Get-Service
}
再:
Invoke-Command -Session $Session
-ScriptBlock {
Get-Process
}
這兩次都使用同一個:
PSSession
用完 Session 要記得清掉
可以:
Remove-PSSession $Session
這就跟 Day 6 提到的:
建立 Connection
↓
工作
↓
工作完成
↓
關閉 Connection
很像。
如果是正式 Script,也很適合搭配:
try
catch
finally
例如:
$Session = $null
try {
$Session = New-PSSession `
-ComputerName SERVER01 `
-ErrorAction Stop
Invoke-Command `
-Session $Session `
-ScriptBlock {
hostname
}
}
catch {
Write-Host $_.Exception.Message
}
finally {
if ($null -ne $Session) {
Remove-PSSession $Session
}
}
這就是 finally 真正很適合出現的情境之一。
Invoke-Command 還是 PSSession?
可以先簡單這樣分。
情境 建議
執行一次指令 Invoke-Command
對很多台 Server 做一次巡檢 Invoke-Command
需要對同一 Server 做很多連續操作 PSSession
需要保留遠端 Session 狀態 PSSession
目前我們做的是:
每日批次巡檢。
所以我會先以:
Invoke-Command
為主。
不用一開始把事情做得太複雜。
Remote Object 有一點需要知道
假設:
$Result = Invoke-Command -ComputerName SERVER01
-ScriptBlock {
Get-Service W32Time
}
拿回本機之後,這個 Object 並不完全等同:
Get-Service W32Time
直接在本機取得的物件。
Remoting 通常會把物件序列化之後傳回來。
所以你可能會看到:
Deserialized.System.ServiceProcess.ServiceController
這代表:
資料傳回來了,但它不一定還保留原本所有可以直接操作的方法。
例如遠端拿回來的 Service Object,不要想成拿回本機之後再:
$Result.Stop()
就能直接控制遠端 Service。
比較好的思考方式是:
需要在 Remote Server 上執行的動作
↓
放在 ScriptBlock 裡做
需要帶回來分析的資料
↓
回傳 Object
這個差別之後會很重要。
多台巡檢時,我建議回傳乾淨的 PSCustomObject
例如不要直接:
Get-CimInstance Win32_OperatingSystem
把一大堆 Property 全部傳回來。
而是在 Remote Server 上先整理:
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
CPU = $CPUUsage
Memory = $MemoryUsage
Uptime = $Uptime.TotalDays
}
再傳回管理端。
也就是:
Remote Server
↓
取得原始資料
↓
計算
↓
整理
↓
只傳需要的結果
↓
Management Server
這樣:
網路傳輸比較少
報表比較乾淨
Script 比較容易維護
今天完整範例:Multi-Server Health Check
把前面的東西整理成一版:
$Servers = @(
"SERVER01"
"SERVER02"
"SERVER03"
)
$ReportFolder = "C:\Temp"
$Date = Get-Date -Format "yyyyMMdd"
$ReportFile = "$ReportFolder\Multi_Server_Health_$Date.csv"
if (-not (Test-Path $ReportFolder)) {
New-Item `
-Path $ReportFolder `
-ItemType Directory |
Out-Null
}
$Results = @()
foreach ($Server in $Servers) {
Write-Host "Checking $Server..."
try {
# Check WinRM
Test-WSMan `
-ComputerName $Server `
-ErrorAction Stop |
Out-Null
# Remote Health Check
$RemoteResult = Invoke-Command `
-ComputerName $Server `
-ErrorAction Stop `
-ScriptBlock {
# CPU
$CPUUsage = [math]::Round(
(
Get-CimInstance Win32_Processor |
Measure-Object `
-Property LoadPercentage `
-Average
).Average,
2
)
# OS / Memory
$OS = Get-CimInstance Win32_OperatingSystem
$MemoryUsage = [math]::Round(
(
(
$OS.TotalVisibleMemorySize -
$OS.FreePhysicalMemory
) /
$OS.TotalVisibleMemorySize
) * 100,
2
)
# Uptime
$Uptime = (Get-Date) - $OS.LastBootUpTime
# CPU Status
if ($CPUUsage -ge 90) {
$CPUStatus = "Critical"
}
elseif ($CPUUsage -ge 80) {
$CPUStatus = "Warning"
}
else {
$CPUStatus = "Normal"
}
# Memory Status
if ($MemoryUsage -ge 90) {
$MemoryStatus = "Critical"
}
elseif ($MemoryUsage -ge 80) {
$MemoryStatus = "Warning"
}
else {
$MemoryStatus = "Normal"
}
# Result
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
Connection = "Success"
CPUUsage = $CPUUsage
CPUStatus = $CPUStatus
MemoryUsage = $MemoryUsage
MemoryStatus = $MemoryStatus
LastBootTime = $OS.LastBootUpTime
UptimeDays = [math]::Round(
$Uptime.TotalDays,
1
)
ErrorMessage = ""
CheckTime = Get-Date
}
}
$Results += $RemoteResult
}
catch {
$Results += [PSCustomObject]@{
ComputerName = $Server
Connection = "Failed"
CPUUsage = $null
CPUStatus = "Unknown"
MemoryUsage = $null
MemoryStatus = "Unknown"
LastBootTime = $null
UptimeDays = $null
ErrorMessage = $_.Exception.Message
CheckTime = Get-Date
}
}
}
$Results |
Select-Object `
ComputerName,
Connection,
CPUUsage,
CPUStatus,
MemoryUsage,
MemoryStatus,
UptimeDays
$Results |
Select-Object ComputerName, Connection, CPUUsage, CPUStatus, MemoryUsage, MemoryStatus, LastBootTime, UptimeDays, ErrorMessage, CheckTime | Export-Csv
-Path $ReportFile -NoTypeInformation
-Encoding UTF8
Write-Host ""
Write-Host "Health Check Completed"
Write-Host "Report: $ReportFile"
執行結果可能是
ComputerName Connection CPUUsage CPUStatus MemoryUsage MemoryStatus UptimeDays
SERVER01 Success 20 Normal 62.5 Normal 13.1
SERVER02 Failed Unknown
SERVER03 Success 85 Warning 73.2 Normal 5.8
第一眼就可以看到:
SERVER02
→ Connection Failed
以及:
SERVER03
→ CPU Warning
工程師就不用從三台 Server 的完整資料開始翻。
真正環境還有權限問題
Remoting 很常遇到:
Access is denied
這時候不是:
Server Down
而可能單純是:
目前登入的帳號沒有足夠權限。
這也是為什麼我會把:
Connection
和:
Server Health
分開。
例如:
SERVER01
Connection = Success
Health = Warning
以及:
SERVER02
Connection = Failed
Health = Unknown
Unknown 比亂猜成:
Critical
合理很多。
因為:
沒有取得資料,就應該承認目前不知道狀態。
這其實也是做監控與自動化很重要的觀念。
不要把系統管理帳密直接寫進 Script
有時候可能會看到:
$username = "Administrator"
$password = "MyPassword123"
再把帳密直接放進 Script。
這不建議。
因為:
.ps1
本質上就是可以直接開啟閱讀的文字檔。
如果日後要處理:
Credential
Secret
Service Account
應該使用更適合的 Credential / Secret 管理方式,並遵循公司的帳號與權限政策。
這個系列後面如果需要再獨立處理。
現在先不要為了方便,把管理員密碼寫進 .ps1。
最小權限也是重點
也不要因為 PowerShell Remoting 需要權限,就直接認為:
所有人都給 Domain Admin 最簡單。
企業環境應該考慮:
誰可以遠端管理?
可以管理哪些 Server?
允許執行哪些工作?
帳號是否有 Log?
權限是否可以再縮小?
我們今天的 Lab 可以先把功能做出來。
但真正 Production Environment:
能做到,不代表就應該給最大權限去做。
今天真正跨過的是哪個門檻?
其實今天沒有學很多新的「巡檢項目」。
CPU 還是:
Get-CimInstance Win32_Processor
Memory 還是:
Get-CimInstance Win32_OperatingSystem
前面都學過。
真正改變的是執行架構。
以前:
工程師
↓
登入 SERVER01
↓
執行 Script
現在:
Engineer
│
▼
Management Host
│
PowerShell Remoting
│
┌───────────┼───────────┐
▼ ▼ ▼
SERVER01 SERVER02 SERVER03
│ │ │
└───────────┼───────────┘
▼
Report
也就是從:
單機 Automation
開始走向:
集中式 Automation。
Day 10 小結
今天主要碰到了:
Test-WSMan
Invoke-Command
New-PSSession
Get-PSSession
Remove-PSSession
Test-NetConnection
最核心的還是:
Invoke-Command -ComputerName SERVER01
-ScriptBlock {
# Remote Command
}
然後進一步把:
SERVER01
SERVER02
SERVER03
全部納入同一份巡檢流程。
到目前為止,我們的工具已經具備:
多台 Server
↓
Remoting
↓
錯誤處理
↓
CPU
Memory
Uptime
↓
Status
↓
CSV Report
前十天如果用一句話總結,就是:
我們已經從一條 PowerShell 指令,慢慢做成一支可以集中巡檢多台 Windows Server 的工具。
這個階段我反而不建議急著一直加新功能。
接下來應該開始整理程式結構,否則 Script 會越來越長,最後自己也不敢改。
Day 11 預告
Day 11|把 PowerShell Script 拆成 Function:別讓巡檢工具變成 500 行的大檔案
目前程式已經包含:
Connectivity
CPU
Memory
Disk
Service
Uptime
Event Log
Remoting
CSV
Error Handling
Log
如果全部一直往同一個 .ps1 裡面加,最後可能會變成:
HealthCheck.ps1
700 行
然後幾個月後:
「這一段到底誰會用到?」
所以 Day 11 我建議先暫停增加巡檢項目,開始重構。
我們會把原本的程式拆成:
Test-ServerConnection
Get-CPUHealth
Get-MemoryHealth
Get-DiskHealth
Get-ServiceHealth
Get-UptimeInfo
Get-EventHealth
Write-Log
最後主程式可能只剩:
讀 Server List
↓
呼叫 Function
↓
收集 Result
↓
產生 Report
Day 11 會是這個 30 天系列第一次從「把功能做出來」開始轉向「把工具寫得可以維護」。