上一篇先聊了為什麼系統工程師需要自動化。
到了 Day 2,我們正式開始碰 PowerShell。
不過這一篇我不打算一次塞很多語法,因為剛開始學 PowerShell 時,如果先背一堆:
if
foreach
while
function
array
hashtable
很容易看了很多,實際工作時還是不知道該從哪一條指令開始。
所以今天先做一件比較重要的事情:
學會怎麼找到指令、看懂指令,以及把系統資料抓出來。
這幾個能力熟悉之後,後面不管是 AD、Windows Server、Service、Process 或 Event Log,其實都會一直重複用到。
先確認 PowerShell 可以正常使用
Windows 10、Windows 11 與 Windows Server 本身都有 PowerShell。
可以先開啟:
開始功能表
↓
搜尋 PowerShell
↓
Windows PowerShell
也可以使用 Windows Terminal。
開啟後先輸入:
$PSVersionTable
會看到類似:
Name Value
PSVersion 5.1.xxxxx.xxxx
PSEdition Desktop
如果是 PowerShell 7,則可能看到:
PSVersion 7.x.x
PSEdition Core
這個系列有不少內容會碰到 Windows Server 與 Active Directory,所以實驗時使用 Windows PowerShell 5.1 其實就已經足夠。
PowerShell 指令看起來為什麼都很像?
PowerShell 有一個很好辨認的命名方式:
Verb-Noun
也就是:
動作-東西
例如:
Get-Service
意思就是:
Get
取得
Service
服務
所以:
Get-Service
就是:
取得 Windows Service 資訊。
另外像:
Get-Process
就是取得 Process。
Stop-Service
就是停止 Service。
Start-Service
就是啟動 Service。
這種命名方式有一個很大的好處:
就算沒有把指令全部背起來,也有機會猜出它大概叫什麼。
第一個要學的不是 Get-Service,而是 Get-Command
我覺得剛開始使用 PowerShell,最值得先記住的指令其實是:
Get-Command
因為我們不可能記住所有 Cmdlet。
例如今天我想知道:
有哪些跟 Service 有關的指令?
可以輸入:
Get-Command Service
可能會看到:
Get-Service
New-Service
Restart-Service
Resume-Service
Set-Service
Start-Service
Stop-Service
Suspend-Service
這樣就不用 Google:
PowerShell 怎麼停止 Windows Service?
直接從 PowerShell 裡面找。
如果想知道有哪些 Get 開頭的指令:
Get-Command -Verb Get
或是找 Process 相關的:
Get-Command Process
這個習慣在之後非常有用。
因為實際做系統維運時,很常發生:
我知道 PowerShell 應該做得到,但我忘記指令叫什麼。
這時 Get-Command 就很好用。
找到指令後,下一步是 Get-Help
假設我們找到:
Get-Service
但是不知道怎麼用。
可以直接:
Get-Help Get-Service
PowerShell 會告訴我們:
這個 Cmdlet 做什麼
有哪些參數
語法怎麼寫
如果想看範例:
Get-Help Get-Service -Examples
這個我非常常用。
例如可能看到:
Get-Service
或:
Get-Service -Name "w32time"
如果想看更完整的資訊:
Get-Help Get-Service -Full
所以遇到不知道怎麼使用的指令時,我現在通常會先:
Get-Command
↓
Get-Help
↓
實際執行
而不是第一時間直接找網頁。
開始做第一個系統查詢:Get-Service
接下來實際查一下 Windows Service。
輸入:
Get-Service
會看到類似:
Status Name DisplayName
Running Appinfo Application Information
Stopped BITS Background Intelligent Transfer...
Running EventLog Windows Event Log
Running LanmanServer Server
Running Winmgmt Windows Management Instrumentation
這裡就已經拿到三個很重要的資訊:
Status
Name
DisplayName
例如只想找 Windows Update:
Get-Service -Name wuauserv
可能看到:
Status Name DisplayName
Running wuauserv Windows Update
這其實已經是一個很基本的維運動作。
以前我們可能會:
Win + R
↓
services.msc
↓
找 Windows Update
↓
確認狀態
現在只需要:
Get-Service wuauserv
找出所有正在執行的 Service
接著來做一點篩選。
Get-Service | Where-Object Status -eq "Running"
結果只會留下:
Running
的 Service。
這裡第一次出現:
|
也就是 Pipeline。
可以先把它理解成:
把前一個指令的結果交給下一個指令。
所以:
Get-Service |
Where-Object Status -eq "Running"
可以理解為:
取得所有 Service
↓
交給 Where-Object
↓
只留下 Status = Running
這個概念之後會大量使用。
接著看看 Process
另一個系統工程師常碰到的就是 Process。
輸入:
Get-Process
可能看到:
Handles NPM(K) PM(K) WS(K) CPU(s) Id ProcessName
...
如果要查 Chrome:
Get-Process chrome
如果 Chrome 有開很多分頁,通常會看到很多個 Process。
也可以依照 CPU 使用時間排序:
Get-Process |
Sort-Object CPU -Descending
再只看前 10 個:
Get-Process |
Sort-Object CPU -Descending |
Select-Object -First 10
這就開始有一點維運巡檢的感覺了。
整個流程是:
取得 Process
↓
依 CPU 排序
↓
從大到小
↓
取前 10 個
PowerShell 很重要的一件事:它處理的是 Object
這是今天最重要的觀念。
很多人從 CMD 或 Linux Shell 過來時,會下意識把 PowerShell 看成:
一個可以輸入 Windows 指令的黑色視窗。
但 PowerShell 有一個很大的特色:
PowerShell Pipeline 傳遞的主要不是單純文字,而是 Object。
例如:
Get-Service
畫面上看到:
Status
Name
DisplayName
看起來好像只是一張文字表格。
但實際上,每一個 Service 都是一個物件。
裡面還有很多目前沒有顯示出來的資訊。
使用 Get-Member 看看物件裡有什麼
我們可以輸入:
Get-Service | Get-Member
這時會看到很多內容,例如:
CanPauseAndContinue
CanShutdown
CanStop
DisplayName
MachineName
ServiceName
Status
Start
Stop
Pause
Refresh
這些大致可以分成:
Property
Method
可以先簡單理解:
Property
就是這個物件擁有的資料。
例如:
Status
DisplayName
ServiceName
Method
則是這個物件可以執行的動作。
例如:
Start()
Stop()
Refresh()
今天不用把 Object 的所有細節全部學完。
先記住一件事情就好:
看到 PowerShell 指令的輸出,不代表畫面上顯示的欄位就是全部資料。
很多資料其實都藏在 Object 裡。
Select-Object:我要哪些欄位自己決定
例如:
Get-Process
預設會顯示一些資訊。
但如果我只想要:
Process Name
Process ID
CPU
可以:
Get-Process |
Select-Object ProcessName, Id, CPU
結果會變成:
ProcessName Id CPU
chrome 5236 28.31
explorer 6148 5.82
powershell 7392 1.44
這個技巧非常重要。
因為之後做維運報表時,我們很少需要把所有資料全部輸出。
通常只需要:
Hostname
Username
LastLogonDate
Enabled
或:
ServerName
CPU
Memory
Disk
Status
所以 Select-Object 後面會一直出現。
Where-Object:把不要的資料過濾掉
例如找停止中的 Service:
Get-Service |
Where-Object Status -eq "Stopped"
也可以寫成比較完整的形式:
Get-Service |
Where-Object {
$_.Status -eq "Stopped"
}
這裡的:
$_
可以暫時理解為:
Pipeline 裡目前正在處理的這一筆資料。
所以:
$_.Status
就是:
這一筆 Service 的 Status。
後面查 AD User 時會大量看到這個寫法。
Sort-Object:把結果整理一下
例如依 Process CPU 排序:
Get-Process |
Sort-Object CPU -Descending
如果是依名稱:
Get-Service |
Sort-Object Name
這些小工具之後可以慢慢組合。
例如:
Get-Process |
Where-Object CPU -gt 10 |
Sort-Object CPU -Descending |
Select-Object ProcessName, Id, CPU
意思是:
取得全部 Process
↓
CPU 大於 10
↓
CPU 從高到低排序
↓
只留下 ProcessName、ID、CPU
這就是 PowerShell 很核心的操作方式。
Pipeline 才是 PowerShell 真正好用的地方
今天目前學到:
Get-Process
取得資料。
接著可以:
Where-Object
過濾。
再:
Sort-Object
排序。
最後:
Select-Object
挑選欄位。
串起來就是:
Get-Process |
Where-Object CPU -gt 10 |
Sort-Object CPU -Descending |
Select-Object ProcessName, Id, CPU
可以把它想成一條資料處理流程:
Get
↓
Filter
↓
Sort
↓
Select
↓
Output
後面 30 天其實會一直重複這個模式。
只是資料來源會慢慢改變:
Get-Service
Get-Process
Get-WinEvent
Get-ADUser
Get-ADComputer
今天做一個簡單的小練習
假設現在我要確認:
哪些 Service 目前是停止的?
第一版:
Get-Service |
Where-Object Status -eq "Stopped"
再把它按照名稱排序:
Get-Service |
Where-Object Status -eq "Stopped" |
Sort-Object Name
只留下我要的欄位:
Get-Service |
Where-Object Status -eq "Stopped" |
Sort-Object Name |
Select-Object Name, DisplayName, Status
這已經算是一個很小的維運查詢。
再試一次 Process
找出 CPU 使用時間最高的前 5 個 Process:
Get-Process |
Sort-Object CPU -Descending |
Select-Object -First 5 ProcessName, Id, CPU
例如:
ProcessName Id CPU
chrome 5520 321.8
Teams 8840 218.4
explorer 3612 92.1
Code 9264 71.3
powershell 7420 18.2
要特別注意:
Get-Process 的 CPU 通常是 Process 累積使用的 CPU 時間,不是工作管理員裡看到的即時 CPU 百分比。
這兩個不要直接畫上等號。
之後做真正 Server Health Check 時,我們再處理即時 CPU 使用率。
我不建議一開始背一大堆 PowerShell 指令
今天如果真的要記,我只會先記這幾個:
Cmdlet 用途
Get-Command 找 PowerShell 指令
Get-Help 查詢使用方式
Get-Member 查看 Object 有哪些資料
Get-Service 查 Windows Service
Get-Process 查 Process
Where-Object 篩選
Sort-Object 排序
Select-Object 選擇欄位
真正需要養成的習慣反而是:
不知道指令
↓
Get-Command
不知道怎麼用
↓
Get-Help
不知道有哪些欄位
↓
Get-Member
只要這三件事情會,之後遇到新的 PowerShell Cmdlet,就不需要每次都從頭開始。
Day 2 小結
今天其實還沒有真正開始寫 Script。
但已經建立幾個後面非常重要的基礎:
Cmdlet
↓
Object
↓
Pipeline
↓
Filter
↓
Sort
↓
Select
其中我覺得最重要的還是:
不要把 PowerShell 當成另一個 CMD。
CMD 很多時候是在處理文字。
PowerShell 更像是在:
取得一批系統物件,再對這批資料進行篩選、整理與處理。
等這個概念熟悉之後,後面做 Active Directory 時,就會看到很類似的東西:
Get-ADUser
取得 User Object。
接著:
Where-Object
Select-Object
Sort-Object
其實操作思路是一樣的。