1. PowerShell 概述
PowerShell 是由微软开发的一种跨平台任务自动化和配置管理框架,由命令行 Shell 和脚本语言组成。它基于 .NET 框架,可以运行在 Windows、macOS 和 Linux 系统上。PowerShell 的强大之处在于其能够访问和管理系统的所有资源,包括文件系统、注册表、网络等。
**PowerShell 通过 cmdlet(发音为 “command-let”)来执行任务。**每个 cmdlet 通常由一个动词和一个名词组成,例如 Get-Process 用于获取进程信息。PowerShell 还支持面向对象的管道(Pipeline),允许 cmdlet 之间传递对象,而不仅仅是文本。
这也是它和 Unix Shell 最大的差异:Bash 擅长把文本流串起来,PowerShell 擅长把结构化对象传下去。做 Windows 管理、Microsoft 生态自动化、跨平台运维脚本时,PowerShell 不是“另一个 shell”,而是一套围绕对象和系统 API 组织的自动化接口。
2. 与其他 Shell 对比
| 比较维度 | PowerShell | CMD | Bash | Zsh |
|---|---|---|---|---|
| 平台支持 | 跨平台(Windows, Mac, Linux) | Windows | Unix 系统(Linux, Mac) | Unix 系统(Linux, Mac) |
| 开发公司 | 微软 | 微软 | GNU | 开源社区 |
| 对象模型 | 面向对象,操作 .NET 对象 | 基于字符串处理 | 基于字符串处理 | 基于字符串处理 |
| 管道机制 | 支持对象管道 | 不支持 | 支持字符串管道 | 支持字符串管道 |
| 脚本扩展名 | .ps1 | .bat, .cmd | .sh | .zsh |
| 主要用途 | 系统管理、自动化脚本 | 简单任务自动化、批处理 | 系统管理、自动化脚本、服务器管理 | 系统管理、自动化脚本、服务器管理 |
| 交互界面 | 图形界面(PowerShell ISE, VS Code) | 无图形界面 | 无图形界面 | 无图形界面 |
| 错误处理 | 高级错误处理机制(try/catch) | 简单的错误处理(if errorlevel) | 基本错误处理 | 基本错误处理 |
| 模块系统 | 丰富的模块和包管理系统(PSGallery) | 无模块系统 | 基于文件和库 | 基于文件和库 |
| 脚本调试 | 强大的调试工具(断点、变量监视) | 无直接调试工具 | 基本调试工具(set -x, trap) | 基本调试工具(set -x, trap) |
| 命令别名 | 支持丰富的命令别名 | 支持少量命令别名 | 支持命令别名 | 支持强大的命令别名(包括 Bash 支持的所有别名) |
| 扩展性 | 高度扩展性,通过 .NET 库和第三方模块 | 低扩展性 | 中等扩展性,通过脚本和第三方工具 | 高度扩展性,通过插件系统 |
| 内置命令 | 丰富的内置 cmdlet 和函数 | 基本的内置命令 | 丰富的内置命令 | 丰富的内置命令 |
| 学习曲线 | 相对陡峭,需要了解 .NET 对象模型 | 平缓,易于上手 | 中等,需要了解 Unix 系统和命令 | 中等,需要了解 Unix 系统和命令 |
| 文档支持 | 强大的内置帮助系统(Get-Help) | 基本的帮助命令(help, /?) | 丰富的在线文档和社区支持 | 丰富的在线文档和社区支持 |
| 社区支持 | 活跃的官方和社区支持 | 基本的官方和社区支持 | 广泛的社区支持 | 广泛的社区支持 |
3. 环境入口
PowerShell 7 之后已经是跨平台工具,命令入口通常是 pwsh。Windows 管理场景仍然最常见,macOS/Linux 上则更适合处理 Microsoft 云服务、跨平台脚本和对象化数据管道。
Update-Help 可以更新本地帮助文档;执行策略(如 RemoteSigned)影响脚本能否运行。执行策略不是完整安全边界,只是误执行脚本的一层防护,真正的边界仍然是脚本来源、签名、权限和审计。
4. Cmdlet 命名规范
**PowerShell 的 cmdlet 以 “动词 - 名词” 形式命名,动词描述动作,名词描述操作对象。**这种规范让命令可搜索、可补全,也让脚本更接近自然语言。例如:
Get-Process # 获取当前运行的进程
Set-Location # 设置当前工作目录常用动词
| 动词 | 用途说明 | 示例 |
|---|---|---|
Get | 获取信息或对象 | Get-Process 获取进程信息 |
Set | 设置或配置对象 | Set-Location 设置工作目录 |
New | 创建新的对象 | New-Item 创建文件或目录 |
Remove | 删除对象 | Remove-Item 删除文件或目录 |
Start | 启动操作或进程 | Start-Process 启动进程 |
Stop | 停止操作或进程 | Stop-Process 停止进程 |
Test | 测试或验证操作 | Test-Connection 测试网络连接 |
Export | 导出数据 | Export-Csv 导出到 CSV 文件 |
Import | 导入数据 | Import-Csv 从 CSV 文件导入数据 |
Invoke | 执行操作 | Invoke-Command 执行命令 |
5. 管道与对象流
PowerShell 的管道(Pipeline)允许将一个 cmdlet 的输出直接传递给下一个 cmdlet 作为输入。与 Unix Shell 不同,PowerShell 管道传递的是对象而非纯文本,这使得数据处理更加直观和灵活。
# 获取所有进程,筛选出 CPU 使用率大于 100 的进程
Get-Process | Where-Object { $_.CPU -gt 100 }$_ 表示管道中的当前对象,后接属性名即可访问对象属性。判断一段 PowerShell 是否可靠,关键要看它是否在处理真实对象属性,而不是把格式化后的文本再拿来解析。
# 获取所有已停止的服务并重新启动它们
Get-Service | Where-Object { $_.Status -eq 'Stopped' } | Start-Service6. 获取帮助
PowerShell 提供了强大的内置帮助系统,Get-Help 是学习和查找 cmdlet 详细信息的最佳方式:
Get-Help Get-Process使用 Update-Help 更新本地帮助文件以获取最新文档:
Update-Help7. 变量与数据类型
变量以 $ 符号开头,PowerShell 变量是动态类型的,无需提前声明类型:
$name = "John"
$age = 30
$fruits = @("Apple", "Banana", "Cherry")
Write-Output "Name: $name, Age: $age"数据类型
| 数据类型 | 描述 | 示例 |
|---|---|---|
| 字符串(String) | 文本数据 | $string = "Hello, World!" |
| 整数(Integer) | 整数型数值 | $integer = 42 |
| 浮点数(Float) | 浮点型数值 | $float = 3.14 |
| 数组(Array) | 有序集合 | $array = @(1, 2, 3, 4, 5) |
| 哈希表(Hashtable) | 键值对集合 | $hashtable = @{ Name = "Alice"; Age = 25 } |
8. 运算符
算术运算符
| 运算符 | 描述 | 示例 |
|---|---|---|
+ | 加法 | $a + $b |
- | 减法 | $a - $b |
* | 乘法 | $a * $b |
/ | 除法 | $a / $b |
% | 取模(余数) | $a % $b |
比较运算符
| 运算符 | 描述 | 示例 |
|---|---|---|
-eq | 等于 | $a -eq $b |
-ne | 不等于 | $a -ne $b |
-gt | 大于 | $a -gt $b |
-ge | 大于或等于 | $a -ge $b |
-lt | 小于 | $a -lt $b |
-le | 小于或等于 | $a -le $b |
逻辑运算符
| 运算符 | 描述 | 示例 |
|---|---|---|
-and | 与 | $a -and $b |
-or | 或 | $a -or $b |
-not | 非 | -not $a |
特殊运算符
| 运算符 | 描述 | 示例 |
|---|---|---|
-match | 正则表达式匹配 | $string -match "Power" |
-like | 通配符匹配 | $string -like "Power*" |
-contains | 检查数组是否包含元素 | $array -contains 3 |
9. 流程控制
条件语句
if / else
$a = 10
if ($a -gt 5) {
Write-Output "a is greater than 5"
} elseif ($a -eq 5) {
Write-Output "a is equal to 5"
} else {
Write-Output "a is less than 5"
}switch
$day = "Tuesday"
switch ($day) {
"Monday" { Write-Output "Today is Monday" }
"Tuesday" { Write-Output "Today is Tuesday" }
"Wednesday" { Write-Output "Today is Wednesday" }
default { Write-Output "Today is another day" }
}循环语句
for
for ($i = 0; $i -lt 5; $i++) {
Write-Output "Iteration $i"
}foreach
$array = @(1, 2, 3, 4, 5)
foreach ($item in $array) {
Write-Output "Item: $item"
}while
$i = 0
while ($i -lt 5) {
Write-Output "Iteration $i"
$i++
}do-while
$i = 0
do {
Write-Output "Iteration $i"
$i++
} while ($i -lt 5)10. 脚本编写基础
PowerShell 脚本文件的扩展名为 .ps1,可以用任何文本编辑器编写,然后在 PowerShell 中运行:
# hello.ps1
$name = "World"
Write-Output "Hello, $name!".\hello.ps1脚本参数
通过 param 关键字定义参数,使脚本更灵活:
# greet.ps1
param (
[string]$name = "World"
)
Write-Output "Hello, $name!".\greet.ps1 -name "Alice"注释
使用 # 添加单行注释,使用 <# ... #> 添加多行注释:
# 这是单行注释
Write-Output "Single-line comment."
<#
这是多行注释
可以跨越多行
#>
Write-Output "Multi-line comment."11. 使用原则
先看对象,再看显示:Get-Process 在终端里显示成表格,但管道里传递的是对象。需要调试时,用 Get-Member 看属性和方法。
动词 - 名词是导航系统:不确定命令名时,先猜动词和对象,再用 Get-Command -Verb Get 或 Get-Command -Noun Process 搜索。
执行策略不是安全银弹:不要运行来路不明的 .ps1;自动化脚本要保留来源、参数、日志和权限边界。
跨平台时避免 Windows 假设:路径分隔符、注册表、服务管理、换行和编码都可能不同。能用跨平台 cmdlet 就不要硬写平台细节。
对象流适合 Agent 和运维自动化:结构化对象比人类表格更稳定。需要给脚本或 Agent 消费时,优先输出对象、JSON 或明确结构,而不是漂亮文本。