PowerShell 腳本
核心理念: PowerShell 不僅僅是命令提示符的升級版,它是構建于 .NET Framework/.NET Core 之上的自動化引擎和腳本語言,融合了命令行的高效與編程語言的強大。
一、 PowerShell 腳本的本質與優勢
- 面向對象 (Object-Oriented):
-
命令 (
Cmdlets) 處理的是對象 (如文件、進程、服務),而非純文本。 -
輸出可通過管道傳遞對象及其豐富屬性 (
Get-Member)。
-
- 強大的管道 (Pipeline):
-
基于對象傳遞 (
Command1 | Command2 | Command3)。 -
支持流式處理,提高效率。
-
過濾 (
Where-Object) 和操作 (ForEach-Object) 對象極為靈活。
-
- 一致的語法 (Verb-Noun):
-
Cmdlets命名遵循動詞-名詞模式 (e.g.,Get-Process,Set-Service,Stop-Job)。 -
提高可發現性和可讀性。
-
- 深度集成 .NET:
-
可直接調用 .NET Framework/Core 類庫,擴展功能無限。
-
[System.Math]::Sqrt(9)或(New-Object System.Net.WebClient).DownloadString('url')。
-
- 可發現性:
-
Get-Command: 查找命令。 -
Get-Help: 獲取詳細幫助 (-Full,-Examples,-Online)。 -
Get-Member: 探索對象屬性與方法。
-
二、 腳本基礎:創建與執行
-
文件擴展名:
.ps1 -
創建腳本:
- 使用任何文本編輯器 (推薦 VS Code + PowerShell 擴展) 或 PowerShell ISE (舊版)。
-
執行腳本:
-
基礎方式:
.\YourScript.ps1(注意點號和反斜杠,表示當前目錄)。 -
關鍵障礙:執行策略 (Execution Policy):
-
目的:防止無意或惡意腳本運行。
-
查看:
Get-ExecutionPolicy -
常見策略:
-
Restricted: (默認) 禁止運行任何腳本。 -
AllSigned: 只運行受信任發布者簽名的腳本。 -
RemoteSigned: (推薦) 本地腳本可運行,下載的腳本需簽名。 -
Unrestricted: (危險) 允許所有腳本運行(有警告)。
-
-
更改 (需管理員權限):
Set-ExecutionPolicy RemoteSigned(通常設置作用域-Scope CurrentUser)。 -
繞過策略 (單次執行):
powershell.exe -ExecutionPolicy Bypass -File .\YourScript.ps1(慎用)。
-
-
三、 腳本核心編程要素
- 變量:
-
定義:
$variableName = value(e.g.,$count = 10,$files = Get-ChildItem). -
弱類型,但可強類型化:
[int]$number = "42"(會轉換)。 -
作用域:
$global:var,$script:var,$private:var,$local:var(默認)。
-
- 數據類型:
-
自動推斷,也可顯式聲明:
[string],[int],[datetime],[array],[hashtable], 自定義 .NET 類型等。 -
GetType()方法查看對象類型。
-
- 運算符:
-
算術:
+,-,*,/,% -
賦值:
=,+=,-=,*=,/= -
比較:
-eq(等于),-ne,-gt,-lt,-ge,-le,-like(通配符),-match(正則),-contains,-in -
邏輯:
-and,-or,-not(!) -
其他:
..(范圍運算符 e.g.,1..5),-is(類型檢查),-as(類型轉換)。
-
- 控制流:
- 條件:
if ($condition) { ... } elseif ($otherCondition) { ... } else { ... }switch語句:
switch -Regex ($value) { 'pattern1' { ... } 'pattern2' { ... } default { ... } } - 循環:
-
foreach ($item in $collection) { ... } -
For ($i = 0; $i -lt $max; $i++) { ... } -
While ($condition) { ... } -
Do { ... } While ($condition)/Do { ... } Until ($condition)
-
- 流控制:
break,continue,return.
- 條件:
- 輸入與輸出:
- 輸入:
-
參數 (見函數部分)。
-
Read-Host "Prompt message"(命令行交互)。 -
管道輸入 (
$input自動變量或在函數/腳本塊中使用param()+ValueFromPipeline)。
-
- 輸出:
-
任何未捕獲或賦值的對象都會輸出到管道/控制臺。
-
顯式輸出:
Write-Output(或直接放置對象),Write-Host(直接到主機,不進入管道,通常僅用于用戶交互信息)。 -
格式化輸出:
Format-Table,Format-List,Format-Wide,Out-GridView(交互式表格)。 -
導出:
Out-File,Export-Csv,Export-Clixml,ConvertTo-Json等。
-
- 輸入:
- 數組與哈希表:
-
數組:
$array = 1, 2, 3或$array = @(1, 2, 3)。索引訪問$array[0]。動態增長。 -
哈希表 (字典):
$hash = @{ Key1 = 'Value1'; Key2 = 'Value2' }。訪問$hash['Key1']或$hash.Key1。用于鍵值對存儲和參數splatting(@hash)。
-
四、 函數:代碼復用的基石
- 基礎函數:
function Get-Greeting { param( [string]$Name = "World" # 帶默認值的參數 ) "Hello, $Name!" } Get-Greeting -Name "PowerShell" - 高級函數:
- 使用
[CmdletBinding()]屬性,獲得類似Cmdlet的功能:- 支持
-Verbose,-Debug,-ErrorAction,-WhatIf,-Confirm等通用參數。 - 顯式參數聲明 (
[Parameter()])。
- 支持
function Get-FileInfo { [CmdletBinding()] param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string[]]$Path ) process { foreach ($p in $Path) { $item = Get-Item $p -ErrorAction SilentlyContinue if ($item) { [PSCustomObject]@{ Name = $item.Name SizeKB = [math]::Round($item.Length / 1KB, 2) LastModified = $item.LastWriteTime } } else { Write-Warning "Path '$p' not found." } } } } Get-ChildItem C:\Temp\*.txt | Get-FileInfo | Format-Table -AutoSize - 使用
- 參數詳解:
-
Mandatory=$true: 強制參數。 -
ValueFromPipeline=$true: 接受管道輸入。 -
ValueFromPipelineByPropertyName=$true: 輸入對象屬性名匹配參數名時綁定。 -
Position=0: 位置參數。 -
ValidateSet('Option1', 'Option2'): 驗證參數值在集合內。 -
ValidatePattern('regex'): 正則驗證。 -
ValidateRange(1, 100): 數值范圍驗證。 -
[Alias('ShortName')]: 為參數定義別名。
-
begin,process,end塊:-
begin: 管道輸入開始前執行一次 (初始化)。 -
process: 對管道輸入的每個對象執行一次 (核心處理邏輯)。 -
end: 所有管道輸入處理完成后執行一次 (清理、匯總)。
-
五、 錯誤處理:構建健壯腳本
- 錯誤類型:
-
終止錯誤 (Terminating Errors): 嚴重錯誤,停止當前命令/腳本執行 (e.g., 語法錯誤、未捕獲異常、
throw語句)。 -
非終止錯誤 (Non-Terminating Errors): 可恢復錯誤,命令繼續執行 (e.g.,
Get-ChildItem訪問部分無權限的文件)。
-
- 錯誤處理機制:
-
-ErrorAction參數: 控制命令對非終止錯誤的處理方式:-
SilentlyContinue: 靜默忽略錯誤,繼續執行。 -
Stop: 將非終止錯誤轉換為終止錯誤。 -
Continue: (默認) 顯示錯誤并繼續。 -
Inquire: 詢問用戶如何處理。
-
-
$ErrorActionPreference變量: 設置當前作用域默認的錯誤操作首選項。 -
try...catch...finally塊: 捕獲和處理終止錯誤。try { # 可能引發終止錯誤的代碼 Get-Content -Path "NonexistentFile.txt" -ErrorAction Stop } catch [System.IO.FileNotFoundException] { Write-Host "文件未找到錯誤: $($_.Exception.Message)" } catch { Write-Host "其他錯誤: $($_.Exception.GetType().FullName)" } finally { # 無論是否出錯都會執行的清理代碼 (e.g., 關閉文件、釋放資源) } -
$Error自動變量: 包含會話中最近錯誤的數組 (最新錯誤在$Error[0])。$_.Exception包含異常的詳細信息。 -
throw語句: 主動拋出終止錯誤。
-
六、 模塊化與代碼組織
- 模塊 (Modules):
-
封裝 PowerShell 功能 (函數、
Cmdlets、變量、別名) 的可復用包。 -
文件擴展名
.psm1(腳本模塊) 或.dll(二進制模塊)。 -
導入模塊:
Import-Module ModuleName。 -
查找模塊:
Find-Module(需注冊 PSRepository,默認是 PowerShellGallery) ->Install-Module->Import-Module。 -
創建模塊: 將相關函數保存在
.psm1文件中,通常伴隨一個描述模塊的.psd1(模塊清單) 文件。New-ModuleManifest創建清單。
-
- 點源加載 (Dot Sourcing):
-
在當前作用域執行另一個腳本文件中的內容 (函數、變量)。
-
語法:
. .\LibraryFunctions.ps1(注意第一個點后有空格)。 -
常用于在腳本間共享函數庫。
-
七、 腳本安全最佳實踐
-
最小特權原則: 腳本運行所需權限。
-
代碼簽名:
-
使用數字證書 (
New-SelfSignedCertificate或購買商業證書) 對腳本簽名 (Set-AuthenticodeSignature)。 -
設置
AllSigned執行策略要求所有腳本必須簽名。
-
-
輸入驗證: 對所有外部輸入 (參數、文件、用戶輸入) 進行嚴格驗證。
-
避免硬編碼敏感信息: 使用安全方式存儲憑據:
-
Get-Credential提示用戶輸入。 -
Export-Clixml加密存儲 (僅限同一用戶同一機器):$cred = Get-Credential $cred | Export-Clixml -Path "C:\secure\mycred.xml" $storedCred = Import-Clixml -Path "C:\secure\mycred.xml" -
企業環境考慮使用密鑰管理系統 (e.g., Azure Key Vault)。
-
-
謹慎處理遠程內容: 驗證下載腳本/配置的來源和完整性。
-
日志記錄: 使用
Start-Transcript,Write-Verbose,Write-Debug,Write-Information或自定義日志函數記錄腳本操作和錯誤。 -
代碼審查: 對重要腳本進行同行審查。
八、 調試技巧
-
集成腳本環境 (ISE) / VS Code:
- 設置斷點、單步執行、查看變量值、調用堆棧。
-
命令行調試:
Set-PSBreakpoint: 在行、變量、命令上設置斷點。Debug-Job: 調試后臺作業。-Debug參數:進入調試模式。
-
Write-Debug語句: 在腳本中插入調試信息,僅當$DebugPreference = 'Continue'或運行腳本時使用-Debug參數時才顯示。 -
$PSBoundParameters/Get-Variable: 查看傳入參數或變量值。 -
Out-GridView/Export-Csv: 將復雜對象輸出到可視化表格或文件查看。
九、 進階主題概覽
-
后臺作業 (
Start-Job,Get-Job,Receive-Job,Remove-Job,Wait-Job): 異步執行任務。 -
計劃任務 (
Register-ScheduledJob,Scheduled Tasks): 定時執行腳本。 -
遠程處理 (
Enter-PSSession,Invoke-Command): 在遠程計算機上執行命令/腳本 (需啟用 WinRM/SSH)。 -
工作流 (
Workflow): 處理長時間運行、需持久化、可并行/序列化步驟的任務 (注意:PowerShell Workflow 在 7.x 中已棄用,考慮替代方案如 Azure 自動化)。 -
類 (
class) (PowerShell 5.0+): 支持定義自定義類,面向對象編程。 -
DSC (Desired State Configuration): 聲明式配置管理框架 (雖然核心發展轉向云原生方案,但概念仍有價值)。
-
PowerShell Core (v6+): 跨平臺 (Windows, Linux, macOS),基于 .NET Core,是未來發展方向。
十、 學習資源
-
官方文檔: Microsoft Docs - PowerShell (https://learn.microsoft.com/en-us/powershell/) 是最權威、最全面的資源。
-
書籍:
- "Learn Windows PowerShell in a Month of Lunches" (經典入門)
- "Windows PowerShell Cookbook" (實用技巧手冊)
- "PowerShell in Depth" (深入詳解)
-
社區:
- PowerShell Gallery (https://www.powershellgallery.com/): 查找和共享模塊、腳本。
- Stack Overflow (https://stackoverflow.com/questions/tagged/powershell): 提問和解答問題。
- Reddit (/r/PowerShell): 社區討論。
- GitHub: 大量開源 PowerShell 項目和腳本。
-
博客: PowerShell Team Blog, 4sysops, Adam the Automator 等。
總結: PowerShell 腳本是強大的自動化工具。掌握其面向對象、管道、函數、錯誤處理、模塊化和安全核心概念,結合實踐和社區資源,能顯著提升 IT 運維、DevOps 和開發效率。從基礎命令開始,逐步構建復雜腳本和模塊,是有效的學習路徑。始終將安全性和健壯性放在首位。

浙公網安備 33010602011771號