公司动态

PowerShell自动化运维实战:从基础命令到脚本编写全解析

📅 2026/8/13 16:00:49
PowerShell自动化运维实战:从基础命令到脚本编写全解析
1. 从“黑窗口”到自动化利器我眼中的PowerShell如果你在Windows上工作肯定见过那个蓝色背景的“Windows PowerShell”窗口。很多人把它当成一个高级版的CMD输入几个dir、ipconfig命令就关掉了。我刚开始也这么想直到有一次我需要给几十台新部署的服务器批量配置环境变量、安装软件并生成报告。手动操作那得干到猴年马月。就是那次我被“逼”着深入使用了PowerShell从此打开了新世界的大门。它远不止一个命令行工具而是一个功能强大的脚本语言和自动化管理框架能帮你把那些繁琐、重复的Windows系统管理任务变成一键执行的脚本。无论是IT运维、开发自测环境搭建还是日常的文件批量处理PowerShell都能让你的效率提升好几个量级。这篇文章我就结合自己这些年踩过的坑和积累的经验跟你聊聊PowerShell那些真正实用、能落地的命令和脚本技巧让你也能从“偶尔用用”变成“得心应手”。2. 核心认知PowerShell与CMD的本质区别在深入具体命令之前我们必须先理清一个根本问题PowerShell和CMD命令提示符到底有什么不同理解这一点你才能明白为什么PowerShell更强大以及该如何正确地使用它。2.1 设计哲学对象管道 vs. 文本流这是最核心的区别。CMD是传统的“文本界面”。你输入命令它输出文本你把一个命令的文本输出通过管道|传递给下一个命令下一个命令再对这些文本进行解析和处理。整个过程就像在流水线上传递一串串字符。而PowerShell是“面向对象”的。它处理的不是纯文本而是.NET对象。当你执行一个命令在PowerShell中称为Cmdlet读作“command-let”它返回的是一个或多个结构化的对象。这些对象有属性描述其特征和方法可以执行的操作。管道在PowerShell中传递的是这些对象而不是它们的文本表示。举个例子获取进程列表。在CMD中你运行tasklist会得到一大段格式固定的文本。如果你想从中找出所有名为“chrome”的进程并计算内存占用总和你需要用findstr过滤文本然后自己写脚本或借助其他工具去解析每一行文本提取出内存数字比如“120,456 K”去掉逗号转换成数字最后再相加。非常繁琐。在PowerShell中你运行Get-Process。它返回的是一个Process对象的集合。每个对象都有Name、Id、CPU、WorkingSet内存等属性。你可以直接这样操作# 获取所有Chrome进程并计算它们的工作集内存总和单位MB (Get-Process -Name chrome).WorkingSet | Measure-Object -Sum | Select-Object -ExpandProperty Sum | ForEach-Object { [math]::Round($_ / 1MB, 2) }这条命令的思维过程是获取对象 - 选择属性 - 进行数学计算。你完全不需要关心文本格式。注意正因为PowerShell输出的是对象当你看到屏幕上显示的内容时那只是该对象默认的文本视图。对象本身包含的信息可能多得多。可以使用Get-Member命令别名gm来查看一个对象的所有属性和方法例如Get-Process | Get-Member。2.2 命令体系Cmdlet的命名规范PowerShell的命令Cmdlet遵循一个严格的“动词-名词”命名约定如Get-Process、Set-Service、Stop-Computer。这种命名方式非常清晰一致让你很容易猜出一个命令是干什么的。动词描述了操作如 Get获取、Set设置、New新建、Remove删除、Start启动、Stop停止。名词描述了操作的对象如 Process进程、Service服务、Item项目泛指文件、目录等。相比之下CMD的命令是历史遗留的五花八门dir,copy,netstat缺乏统一性。2.3 功能范围一个集成的管理平台CMD主要专注于文件系统和基础系统操作。PowerShell则通过“模块”机制几乎可以管理Windows生态中的一切活动目录AD、Exchange Server、SQL Server、Azure云服务、VMware虚拟化平台等等。它本身就是Windows管理框架如WMI、CIM的最佳接口。实操心得当你需要管理Windows服务器时忘记那些图形界面和零散的GUI工具吧。学习PowerShell写一个脚本可以实现标准化、可重复、可审计的自动化部署与管理。这是现代IT运维的核心技能。3. 生存必备日常高频使用命令详解下面这些命令是我每天都会用到的。掌握它们你就能解决80%的日常问题。3.1 文件与目录操作虽然仍有dir,cd,copy这样的别名为了兼容CMD用户但建议习惯使用PowerShell原生的Cmdlet因为它们功能更强大、更一致。Get-ChildItem(别名ls,dir): 列出目录内容。# 列出当前目录所有内容 Get-ChildItem # 递归列出所有子目录中的.txt文件 Get-ChildItem -Path C:\Logs -Filter *.txt -Recurse # 只显示目录 Get-ChildItem -Directory # 按最后修改时间排序显示最新的10个文件 Get-ChildItem | Sort-Object LastWriteTime -Descending | Select-Object -First 10Set-Location(别名cd): 切换目录。强大之处在于可以访问“特殊”目录。Set-Location C:\Windows # 普通切换 Set-Location HKLM:\Software # 切换到注册表路径 cd Env: # 切换到环境变量“驱动器” cd Cert:\CurrentUser\My # 切换到证书存储Copy-Item(别名copy,cp) 和Move-Item(别名move,mv): 复制和移动。# 复制文件-Force表示强制覆盖已存在文件 Copy-Item source.txt destination.txt -Force # 递归复制整个目录 Copy-Item C:\SourceFolder\* D:\Backup -Recurse # 移动时重命名 Move-Item oldname.txt .\newname.txtRemove-Item(别名del,rm): 删除。请务必谨慎# 删除一个文件 Remove-Item tempfile.log # 递归强制删除一个目录及其所有内容危险 Remove-Item C:\OldFolder -Recurse -Force重要警告-Recurse -Force组合威力巨大且PowerShell默认没有“回收站”机制删除即永久。执行前最好先用-WhatIf参数预览将要执行的操作Remove-Item C:\OldFolder -Recurse -Force -WhatIf。Get-Content(别名cat,type) 和Set-Content: 读取和写入文件内容。# 读取文件显示最后5行 Get-Content app.log -Tail 5 # 读取文件并过滤包含“ERROR”的行 Get-Content app.log | Select-String ERROR # 将字符串写入新文件覆盖 Server configuration log | Set-Content log.txt # 追加内容到文件 New entry at $(Get-Date) | Add-Content log.txt3.2 进程与服务管理Get-Process(别名ps): 获取进程信息。这是排查系统卡顿、内存泄漏的利器。# 获取所有进程按CPU占用降序排列 Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 # 获取指定名称的进程详情 Get-Process -Name explorer | Format-List * # 查找使用超过500MB内存的进程 Get-Process | Where-Object { $_.WorkingSet -gt 500MB }Stop-Process: 结束进程。# 通过进程名结束会结束所有同名进程 Stop-Process -Name notepad -Force # 通过进程ID结束 Stop-Process -Id 1234Get-Service和Start-Service,Stop-Service,Restart-Service: 管理Windows服务。# 获取所有正在运行的服务 Get-Service | Where-Object Status -eq Running # 获取指定服务并查看其依赖 Get-Service -Name wuauserv -RequiredServices # 重启一个服务 Restart-Service -Name Spooler -Force3.3 系统信息与网络Get-ComputerInfo: 获取全面的计算机系统信息PowerShell 5.1及以上。这是一个宝藏命令可以替代很多零散的命令。# 获取所有信息输出很长 Get-ComputerInfo # 获取特定的信息如操作系统和内存 Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, OsTotalVisibleMemorySize, OsFreePhysicalMemoryGet-NetIPConfiguration和Test-NetConnection: 网络配置和诊断。# 类似于 ipconfig /all但输出是对象 Get-NetIPConfiguration -Detailed # 测试到某个主机的连通性类似于 ping但更强大 Test-NetConnection -ComputerName www.bing.com -Port 443 # 这条命令会告诉你DNS解析、ICMP Ping如果允许和指定端口的TCP连接是否成功。3.4 别名与帮助系统Get-Alias: 查看所有别名或查找某个命令的别名。# 查看dir对应哪个原生Cmdlet Get-Alias dir # 查看所有以g开头的别名 Get-Alias g*Get-Help(别名help,man): 最重要的命令之一。PowerShell的帮助文档极其详尽。help Get-Process # 显示标准帮助 help Get-Process -Examples # 只看示例快速上手 help Get-Process -Parameter Name # 查看特定参数的详细说明 help about_* # 查看概念性帮助主题如 help about_aliases实操心得首次使用PowerShell或在新机器上务必运行Update-Help可能需要管理员权限来下载安装最新的帮助文档。离线状态下基本的帮助依然可用但-Online参数可以打开浏览器查看最新在线文档。4. 进阶技巧脚本、管道与对象操作当你熟悉了基本命令后将它们组合起来利用管道和脚本才能发挥PowerShell的真正威力。4.1 管道的精髓筛选、处理和输出管道符号|是PowerShell的灵魂。它传递的是对象因此你可以像流水线一样对对象进行一系列处理。经典模式获取 - 筛选 - 处理 - 输出# 场景清理C盘用户下载目录中超过30天未访问的.log文件 Get-ChildItem -Path $env:USERPROFILE\Downloads -Filter *.log -File | Where-Object { $_.LastAccessTime -lt (Get-Date).AddDays(-30) } | ForEach-Object { # 在删除前将文件信息记录到日志 $logEntry $(Get-Date -Format yyyy-MM-dd HH:mm) - 删除文件: $($_.FullName) 大小: $([math]::Round($_.Length/1KB,2)) KB $logEntry | Add-Content -Path C:\CleanupLog.txt # 删除文件 Remove-Item $_.FullName -Force -Verbose }这个例子清晰地展示了管道流程1) 获取所有.log文件对象2) 用Where-Object筛选出老旧文件3) 用ForEach-Object对每个文件对象执行删除和记录操作。4.2 变量与脚本基础变量以$开头。PowerShell变量是弱类型但强对象的可以存储任何东西。$serviceName Spooler $services Get-Service $today Get-Date脚本.ps1文件将一系列命令保存为.ps1文件。要执行脚本通常需要在PowerShell中设置执行策略。# 以管理员身份运行PowerShell查看当前执行策略 Get-ExecutionPolicy # 通常设置为 RemoteSigned本地脚本可运行远程脚本需签名 Set-ExecutionPolicy RemoteSigned常见问题脚本无法运行。在较新版本的Windows上默认执行策略可能是Restricted禁止所有脚本。如果你只是运行自己写的本地脚本Set-ExecutionPolicy RemoteSigned是平衡安全与便利的常用选择。修改策略需要管理员权限。参数化脚本让你的脚本更灵活。# 保存为 Clean-OldFiles.ps1 param( [string]$Path ., # 目标路径默认为当前目录 [int]$DaysOld 30, # 天数默认30天 [string]$Filter *.tmp # 文件过滤器 ) Get-ChildItem -Path $Path -Filter $Filter -File | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$DaysOld) } | Remove-Item -Force -Verbose Write-Host 清理完成 -ForegroundColor Green运行方式.\Clean-OldFiles.ps1 -Path C:\Temp -DaysOld 7 -Filter *.log4.3 条件与循环if-else判断:$freeSpace (Get-PSDrive C).Free if ($freeSpace -lt 10GB) { Write-Warning C盘空间不足仅剩 $([math]::Round($freeSpace/1GB,2)) GB # 可以在这里触发清理脚本 } elseif ($freeSpace -lt 20GB) { Write-Host C盘空间紧张请注意。 -ForegroundColor Yellow } else { Write-Host C盘空间充足。 -ForegroundColor Green }比较运算符用-eq等于,-ne不等于,-gt大于,-lt小于,-like通配符匹配等而不是,!,,。foreach循环:$computers PC01, PC02, PC03 foreach ($computer in $computers) { $status Test-Connection -ComputerName $computer -Count 1 -Quiet if ($status) { Write-Host $computer 在线 -ForegroundColor Green } else { Write-Host $computer 离线 -ForegroundColor Red } }5. 避坑指南与常见问题解决在实际使用中你肯定会遇到各种奇怪的问题。这里记录了几个最典型的“坑”和解决方法。5.1 执行策略与脚本运行问题问题双击.ps1文件直接打开了记事本或者在PowerShell中运行脚本报错“无法加载文件...因为在此系统上禁止运行脚本”。解决运行方式不要双击.ps1文件。正确做法是在PowerShell控制台中通过路径执行.\你的脚本.ps1注意前面的.\是必须的。或者在文件资源管理器中右键点击.ps1文件选择“使用PowerShell运行”。修改执行策略前文已提# 以管理员身份运行PowerShell Set-ExecutionPolicy RemoteSigned为单次会话绕过策略不推荐长期使用powershell.exe -ExecutionPolicy Bypass -File .\你的脚本.ps15.2 路径与空格问题问题路径中包含空格或特殊字符时命令报错。解决始终用引号将路径括起来特别是包含空格时。使用-LiteralPath参数而不是-Path参数前者将路径视为字面量不解释通配符。# 错误示例 Remove-Item C:\My Documents\file.txt # 正确示例 Remove-Item C:\My Documents\file.txt # 或者使用 LiteralPath Remove-Item -LiteralPath C:\My Documents\file.txt5.3 输出乱码问题问题在VSCode或某些终端中PowerShell输出中文乱码。解决 这通常是控制台编码问题。PowerShell 5.1 默认输出编码可能与终端不匹配。临时修改会话编码[Console]::OutputEncoding [System.Text.Encoding]::UTF8永久修改修改PowerShell配置文件。# 首先检查是否有配置文件 if (!(Test-Path $PROFILE)) { New-Item -Type File -Path $PROFILE -Force } # 用记事本打开配置文件 notepad $PROFILE在配置文件中加入一行[Console]::OutputEncoding [System.Text.Encoding]::UTF8保存重启PowerShell。对于VSCode确保VSCode底部状态栏的编码显示为“UTF-8”或者在其设置中搜索“encoding”进行配置。5.4 命令找不到或无法识别问题在PowerShell中无法运行像java,python,git这样的外部命令。解决 这通常是环境变量PATH的问题。PowerShell有自己的一套环境变量加载逻辑。检查命令是否存在在CMD中运行where java如果能找到说明命令已安装。在PowerShell中刷新PATH# 从系统注册表中重新加载环境变量 $env:Path [System.Environment]::GetEnvironmentVariable(Path,Machine) ; [System.Environment]::GetEnvironmentVariable(Path,User)以管理员身份安装软件后需要重启PowerShell或者手动将安装路径添加到用户环境变量PATH中。对于IDE如IDEA内置的终端有时IDE会启动一个受限或环境变量不同的Shell。尝试在IDE的设置中指定使用系统的PowerShell路径通常是C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe。5.5 脚本运行闪退问题运行脚本时窗口一闪而过。解决脚本本身有错误但错误输出没有被捕获。在脚本开头加入$ErrorActionPreference Stop可以让错误立即停止脚本执行。在脚本末尾加上Read-Host 按回车键退出或Pause命令让窗口暂停。在PowerShell控制台中运行脚本而不是双击这样可以看到完整的错误信息。6. 实战编写一个实用的系统巡检脚本最后我们综合运用以上知识写一个实用的、可以定期运行的系统巡检脚本。这个脚本会收集一些关键的系统状态信息并生成一个简单的HTML报告。# SystemHealthCheck.ps1 # 描述生成系统健康检查报告 param( [string]$ReportPath $env:USERPROFILE\Desktop\SystemHealth_$(Get-Date -Format yyyyMMdd_HHmm).html ) # 1. 收集信息 $computerInfo Get-ComputerInfo | Select-Object CsName, WindowsProductName, WindowsVersion, OsLastBootUpTime $diskInfo Get-PSDrive C | Select-Object Used, Free, {NameUsedPercent; Expression{[math]::Round(($_.Used/($_.Used$_.Free))*100,2)}} $memoryInfo Get-CimInstance Win32_OperatingSystem | Select-Object TotalVisibleMemorySize, FreePhysicalMemory $topProcesses Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name, CPU, WorkingSet, Id $criticalServices Get-Service | Where-Object { $_.Status -ne Running -and $_.StartType -eq Automatic } | Select-Object Name, DisplayName, Status # 2. 生成HTML报告 $htmlContent !DOCTYPE html html head title系统健康检查报告 - $(Get-Date)/title style body { font-family: Arial, sans-serif; margin: 20px; } h1 { color: #333; } .section { margin-bottom: 30px; border: 1px solid #ddd; padding: 15px; border-radius: 5px; } .ok { color: green; } .warning { color: orange; font-weight: bold; } .error { color: red; font-weight: bold; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ccc; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } /style /head body h1系统健康检查报告/h1 p生成时间 $(Get-Date -Format yyyy-MM-dd HH:mm:ss)/p p计算机名 $($computerInfo.CsName)/p div classsection h2系统概览/h2 p操作系统 $($computerInfo.WindowsProductName) ($($computerInfo.WindowsVersion))/p p最后启动时间 $($computerInfo.OsLastBootUpTime)/p p系统运行时长 $([math]::Round(((Get-Date) - $computerInfo.OsLastBootUpTime).TotalHours, 2)) 小时/p /div div classsection h2磁盘空间 (C:)/h2 p已用空间 $([math]::Round($diskInfo.Used/1GB,2)) GB/p p可用空间 $([math]::Round($diskInfo.Free/1GB,2)) GB/p p使用率 span class$(if ($diskInfo.UsedPercent -gt 90) { error } elseif ($diskInfo.UsedPercent -gt 70) { warning } else { ok })$($diskInfo.UsedPercent)%/span/p /div div classsection h2内存状态/h2 p总物理内存 $([math]::Round($memoryInfo.TotalVisibleMemorySize/1MB,2)) GB/p p可用物理内存 $([math]::Round($memoryInfo.FreePhysicalMemory/1MB,2)) GB/p p内存使用率 $([math]::Round(($memoryInfo.TotalVisibleMemorySize - $memoryInfo.FreePhysicalMemory)/$memoryInfo.TotalVisibleMemorySize*100,2))%/p /div div classsection h2CPU占用前5的进程/h2 table trth进程名/ththPID/ththCPU时间/thth内存(MB)/th/tr foreach ($proc in $topProcesses) { $htmlContent trtd$($proc.Name)/tdtd$($proc.Id)/tdtd$([math]::Round($proc.CPU,2))/tdtd$([math]::Round($proc.WorkingSet/1MB,2))/td/trn } $htmlContent /table /div div classsection h2未运行的自动启动服务/h2 if ($criticalServices) { $htmlContent p classerror警告发现 $($criticalServices.Count) 个应自动启动但未运行的服务。/ptabletrth服务名/thth显示名称/thth状态/th/tr foreach ($svc in $criticalServices) { $htmlContent trtd$($svc.Name)/tdtd$($svc.DisplayName)/tdtd$($svc.Status)/td/tr } $htmlContent /table } else { $htmlContent p classok所有自动启动的服务均在运行中。/p } $htmlContent /div /body /html # 3. 保存报告 $htmlContent | Set-Content -Path $ReportPath -Encoding UTF8 Write-Host 系统巡检报告已生成: $ReportPath -ForegroundColor Cyan # 可选自动在浏览器中打开报告 # Start-Process $ReportPath如何使用这个脚本将上面的代码保存为SystemHealthCheck.ps1。在PowerShell中导航到脚本所在目录。运行.\SystemHealthCheck.ps1报告会默认保存在桌面。你可以通过参数指定报告路径.\SystemHealthCheck.ps1 -ReportPath C:\Reports\myreport.html。这个脚本展示了如何组合多个Cmdlet、处理对象、进行条件判断、构建HTML输出并将其保存为文件。你可以根据需要扩展它比如添加网络检查、事件日志查询等功能。定期运行这个脚本例如通过Windows任务计划程序就能自动化地监控你的系统健康状况。