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号