764 字
2 分钟
PowerShell 实用指南
凌晨三点,服务器告警:某个 Windows 服务的日志文件涨到了 50GB,磁盘即将写满。你 SSH 登上去,想用 dir 看看哪些文件最大,输出却只有一串文件名。需要按大小排序?需要筛选扩展名?需要批量压缩?在 CMD 里这些操作要写批处理脚本,但在 PowerShell 里,一条管道命令就够了。PowerShell 不是”加强版的 CMD”,而是一个面向对象的脚本语言,理解它的管道模型和 Cmdlet 体系,日常运维效率可以提升数倍。
一、PowerShell 与 CMD 的区别
1.1 核心差异
| 特性 | CMD | PowerShell |
|---|---|---|
| 数据类型 | 纯文本 | .NET 对象 |
| 管道传递 | 字符串流 | 对象流 |
| 命令命名 | 随意(dir, copy) | 动词-名词(Get-ChildItem) |
| 别名系统 | 无 | 兼容 CMD/Linux 命令别名 |
| 远程管理 | 无原生支持 | WinRM(Windows 远程管理) 原生支持 |
| 脚本语言 | 批处理(极弱) | 完整编程语言 |
| 可扩展性 | 低 | 模块、Cmdlet、Provider |
1.2 版本演进
| 版本 | 系统 | 重大变化 |
|---|---|---|
| 1.0 | Windows XP | 初始版本 |
| 2.0 | Windows 7 | ISE(集成脚本环境)、远程 |
| 3.0 | Windows 8 | 工作流、计划任务 |
| 5.0 | Windows 10 | 类定义、DSC |
| 7.x | 跨平台 | .NET Core 重写,跨平台 |
二、Cmdlet 与管道
2.1 Cmdlet 命名规范
Cmdlet 遵循 动词-名词 命名:
Get-Process # 获取进程Stop-Process # 停止进程Set-Location # 设置位置New-Item # 创建项Remove-Item # 删除项Write-Output # 写入输出常用动词:
| 动词 | 用途 | 示例 |
|---|---|---|
| Get | 查询/获取 | Get-Service |
| Set | 修改/设置 | Set-ExecutionPolicy |
| New | 创建 | New-Item |
| Remove | 删除 | Remove-Item |
| Start | 启动 | Start-Service |
| Stop | 停止 | Stop-Process |
| Add | 添加 | Add-Member |
| Select | 选择 | Select-Object |
| Where | 过滤 | Where-Object |
| ForEach | 遍历 | ForEach-Object |
2.2 管道:对象流
PowerShell 管道传递的是 .NET 对象,不是文本字符串。这是它与 Unix Shell 的本质区别:
# CMD/Unix: 文本处理dir | findstr ".log" | sort
# PowerShell: 对象处理Get-ChildItem | Where-Object { $_.Extension -eq ".log" } | Sort-Object Length -Descending | Select-Object Name, Length, LastWriteTime$_ 是管道中的当前对象变量。
2.3 常用管道命令
# 过滤Get-Process | Where-Object { $_.CPU -gt 100 }
# 选择属性Get-Process | Select-Object Name, CPU, WorkingSet
# 排序Get-ChildItem | Sort-Object Length -Descending
# 分组Get-Process | Group-Object Company
# 统计Get-ChildItem | Measure-Object Length -Sum -Average
# 去重1,2,2,3,3,3 | Select-Object -Unique
# 取前 N 条Get-Process | Select-Object -First 102.4 输出格式化
# 表格Get-Process | Format-Table Name, CPU -AutoSize
# 列表(属性竖排)Get-Process | Format-List Name, CPU, WorkingSet
# 宽格式Get-ChildItem | Format-Wide Name -Column 4
# 自定义Get-Process | Format-Table @{ Label="进程名"; Expression={$_.Name}}, @{ Label="内存(MB)"; Expression={[math]::Round($_.WorkingSet64/1MB, 2)}}三、变量与数据类型
3.1 变量
# 变量以 $ 开头$name = "PowerShell"$count = 42$pi = 3.14159$items = @(1, 2, 3) # 数组$dict = @{ a = 1; b = 2 } # 哈希表
# 强类型[int]$age = 30[string]$title = "Admin"
# 变量作用域$script:config = @{} # 脚本作用域$global:count = 0 # 全局作用域$env:PATH # 环境变量3.2 数据类型
# 基本类型[int] 42[string] "hello"[bool] $true / $false[datetime] Get-Date
# 集合类型[array] @(1, 2, 3)[hashtable] @{ key = "value" }
# .NET 类型[System.IO.FileInfo][System.Net.WebClient][System.Text.StringBuilder]3.3 类型转换
# 显式转换[int]"42" # 字符串 → 整数[string]42 # 整数 → 字符串[datetime]"2025-01-01"
# -as 操作符(转换失败返回 $null 而非报错)"42" -as [int] # 42"hello" -as [int] # $null"3.14" -as [double] # 3.14四、控制流
4.1 条件判断
if ($age -gt 18) { "Adult"} elseif ($age -gt 12) { "Teenager"} else { "Child"}
# switchswitch ($day) { "Monday" { "Start of week" } "Friday" { "End of week" } default { "Midweek" }}
# switch 支持正则和通配符switch -regex ($path) { "\.log$" { "Log file" } "\.txt$" { "Text file" } default { "Unknown" }}4.2 比较操作符
| 操作符 | 含义 | 示例 |
|---|---|---|
-eq | 等于 | $a -eq 10 |
-ne | 不等于 | $a -ne 10 |
-gt | 大于 | $a -gt 10 |
-ge | 大于等于 | $a -ge 10 |
-lt | 小于 | $a -lt 10 |
-le | 小于等于 | $a -le 10 |
-like | 通配符匹配 | "hello" -like "h*" |
-notlike | 通配符不匹配 | "hello" -notlike "x*" |
-match | 正则匹配 | "abc" -match "^a" |
-notmatch | 正则不匹配 | "abc" -notmatch "^x" |
-contains | 集合包含 | @(1,2,3) -contains 2 |
-in | 在集合中 | 2 -in @(1,2,3) |
4.3 循环
# forfor ($i = 0; $i -lt 10; $i++) { Write-Output $i}
# foreachforeach ($item in $collection) { Write-Output $item}
# whilewhile ($condition) { # ...}
# do-whiledo { # 至少执行一次} while ($condition)
# ForEach-Object(管道)1..10 | ForEach-Object { $_ * 2 }五、函数与脚本块
5.1 函数
# 简单函数function Get-Greeting { param( [string]$Name = "World" ) return "Hello, $Name!"}
Get-Greeting -Name "PowerShell"
# 高级函数(支持管道输入)function Get-FileSize { [CmdletBinding()] param( [Parameter(ValueFromPipeline = $true)] [string]$Path ) process { $item = Get-Item $Path [PSCustomObject]@{ Name = $item.Name SizeKB = [math]::Round($item.Length / 1KB, 2) } }}
# 使用管道"C:\temp\file1.txt", "C:\temp\file2.txt" | Get-FileSize5.2 脚本块
# 匿名函数$filter = { $_.Length -gt 1MB }Get-ChildItem | Where-Object $filter
# 调用脚本块$block = { param($x) $x * 2 }& $block 21 # 42
# 传递脚本块function Invoke-Twice { param([scriptblock]$Action) & $Action & $Action}
Invoke-Twice { Write-Output "Hello" }六、文件与注册表操作
6.1 文件操作
# 浏览文件系统Get-ChildItem -Path "C:\temp" -Recurse -Filter "*.log"Set-Location "C:\temp"Get-Location
# 文件读写Get-Content "config.txt" # 读取Set-Content "output.txt" "Hello" # 写入Add-Content "log.txt" "New entry" # 追加Import-Csv "data.csv" | Format-Table # 读取 CSV
# 文件管理Copy-Item "src.txt" "dst.txt"Move-Item "old.txt" "new.txt"Remove-Item "temp.txt" -ForceNew-Item -ItemType File -Path "new.txt"New-Item -ItemType Directory -Path "logs"
# 搜索Select-String -Path "*.log" -Pattern "ERROR"6.2 注册表操作
# 浏览注册表Set-Location HKLM:\SOFTWAREGet-ChildItem
# 读取Get-ItemProperty "HKLM:\SOFTWARE\MyApp"
# 写入New-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" ` -Name "Version" -Value "1.0" -PropertyType String
# 删除Remove-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" -Name "Version"七、远程管理
7.1 WinRM 配置
# 启用 WinRM(需管理员权限)Enable-PSRemoting -Force
# 信任远程主机Set-Item WSMan:\localhost\Client\TrustedHosts "192.168.1.*" -Force
# 测试连接Test-WSMan -ComputerName "server01"7.2 远程执行
# 单次远程命令Invoke-Command -ComputerName "server01" -ScriptBlock { Get-Process | Sort-Object CPU -Descending | Select-Object -First 5}
# 带参数Invoke-Command -ComputerName "server01" -ArgumentList "nginx" -ScriptBlock { param($name) Get-Service -Name $name}
# 多台服务器Invoke-Command -ComputerName "server01", "server02", "server03" -ScriptBlock { Get-Service | Where-Object { $_.Status -eq "Stopped" }}7.3 远程会话
# 建立持久会话$session = New-PSSession -ComputerName "server01"
# 在会话中执行多个命令Invoke-Command -Session $session -ScriptBlock { Get-Process }Invoke-Command -Session $session -ScriptBlock { Get-Service }
# 交互式会话Enter-PSSession -ComputerName "server01"# 现在直接在远程服务器操作Exit-PSSession
# 清理Remove-PSSession $session八、错误处理
8.1 错误类型
# 终止错误(异常)# 非终止错误(错误流)
# 查看错误$Error[0] # 最近一个错误$Error[0].Exception.Message # 错误消息
# 错误偏好设置$ErrorActionPreference = "Stop" # 非终止错误当作终止错误处理8.2 try/catch/finally
try { $result = Get-Content "nonexistent.txt" -ErrorAction Stop} catch [System.IO.FileNotFoundException] { Write-Warning "File not found: $_"} catch { Write-Error "Unexpected error: $_"} finally { # 无论是否出错都会执行 Write-Output "Cleanup done"}8.3 常用错误处理模式
# -ErrorAction 参数Get-ChildItem -Path "C:\maybe-missing" -ErrorAction SilentlyContinue
# -ErrorVariable 捕获错误Get-ChildItem "nonexistent" -ErrorVariable myErr -ErrorAction SilentlyContinueif ($myErr) { Write-Warning "Error occurred: $($myErr[0].Exception.Message)"}九、模块管理
9.1 模块操作
# 查找模块Find-Module -Name "Azure*"
# 安装模块Install-Module -Name "Az" -Scope CurrentUser
# 导入模块Import-Module Az.Compute
# 查看已安装模块Get-Module -ListAvailable
# 查看已加载模块Get-Module
# 更新模块Update-Module "Az"9.2 常用模块
| 模块 | 用途 |
|---|---|
Az | Azure 管理 |
SqlServer | SQL Server 管理 |
ActiveDirectory | AD 域管理 |
Pester | 测试框架 |
PSReadLine | 命令行增强 |
ImportExcel | Excel 操作 |
十、实用技巧
10.1 性能优化
# 差:管道中频繁调用外部命令Get-ChildItem | ForEach-Object { cmd /c "echo $_" }
# 好:使用 PowerShell 原生命令Get-ChildItem | ForEach-Object { Write-Output $_.Name }
# 差:循环中重复查询foreach ($name in $names) { Get-ADUser -Identity $name # 每次都查询}
# 好:一次查询$users = Get-ADUser -Filter { Name -in $names }10.2 安全实践
# 执行策略Get-ExecutionPolicySet-ExecutionPolicy RemoteSigned -Scope CurrentUser
# 安全执行脚本powershell -ExecutionPolicy Bypass -File script.ps1
# 不要在脚本中硬编码密码# 使用 Get-Credential$cred = Get-CredentialInvoke-Command -ComputerName "server01" -Credential $cred -ScriptBlock { ... }
# 使用 SecureString$secPassword = ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force$cred = New-Object System.Management.Automation.PSCredential("admin", $secPassword)10.3 命令速查
| 需求 | 命令 |
|---|---|
| 查找命令 | Get-Command *process* |
| 查看帮助 | Get-Help Get-Process -Full |
| 查看别名 | Get-Alias -Definition Get-ChildItem |
| 查看成员 | `Get-Process |
| 查看类型 | `Get-Process |
| 查看历史 | Get-History |
| 执行历史 | Invoke-History 5 |
参考资料
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时
相关文章 智能推荐
1
x86 汇编语言入门
语言 x86 汇编语言入门——寄存器、指令集、内存寻址与调用约定
2
综合实战:从慢代码到快代码
CPU与计算机体系结构 综合实战——性能分析工作流、哈希表优化案例、网络包处理优化、数据库缓冲池调优,运用前 16 章知识将慢代码变快。
3
Python 进阶指南
语言 Python 进阶指南——装饰器、生成器、上下文管理器、类型注解与性能优化
4
Plan 9 汇编入门
语言 Plan 9 汇编入门——从指令格式到 Go 运行时的汇编实践
5
综合实战:构建 eBPF 网络安全工具
eBPF 综合实战——从零构建 eBPF 网络安全工具——XDP 防 DDoS + TC 流量控制 + LSM 进程监控,运用前 17 章知识解决真实安全问题。






