PowerShell远程执行与数据管理指南
发布时间: 2025-08-13 01:52:10 阅读量: 8 订阅数: 18 


PowerShell自动化实战:从脚本到企业级解决方案
### PowerShell远程执行与数据管理指南
#### 1. 数据保存与CSV文件处理
在进行大量机器检查时,如检查50、500甚至1000台机器,若在检查过程中网络中断或PowerShell控制台关闭,重新启动脚本会从头开始检查所有设备,这会造成时间的巨大浪费。为避免这种情况,可将返回数据保存到PowerShell之外,最简单的方法是将其导出为CSV文件。PowerShell原生支持使用`Import-Csv`和`Export-Csv` cmdlet进行对象与CSV文件的导入和导出,且CSV数据易于人类阅读。
在使用`Export-Csv` cmdlet追加到现有CSV文件时,需注意它只会包含当前标题行中的字段,因此脚本返回的所有数据应使用相同格式。若在每次远程执行后导出结果,当需要重启脚本时可重新导入。具体操作如下:
1. 检查CSV文件是否存在。
2. 若存在,将数据加载到变量中。
3. 使用该变量过滤机器列表,排除已检查的机器。
过滤时,要使用脚本用于创建远程会话的值,而非返回数据中的名称。例如,使用`Invoke-Command` cmdlet时,`PSComputerName`属性会自动添加到输出中,通过对其进行过滤可防止因控制脚本使用FQDN而脚本返回NetBIOS或使用DNS别名导致的重复提交。
另外,为连接失败的机器创建单独的CSV导出文件,这样它们不会与所需的实际结果存储在同一CSV文件中,还能提供一个用于故障排除和修复失败连接的优秀列表。
#### 2. PowerShell通过WS-Management (WSMan)进行远程操作
在Active Directory环境中使用PowerShell时,WSMan是最佳选择。它不仅支持Active Directory身份验证,而且在Windows服务器操作系统上默认启用。还可使用组策略对象 (GPO) 启用WSMan远程操作,使设置更加轻松。
##### 2.1 启用WSMan PowerShell远程操作
目前,只有Windows PowerShell可通过GPO控制,而PowerShell Core不行。若要使用PowerShell 6或更高版本执行远程命令,需在每台服务器上运行`Enable-PSRemoting` cmdlet,可添加`-Force`开关以在启用时避免提示:
```powershell
Enable-PSRemoting -Force
```
若运行`Enable-PSRemoting` cmdlet时收到一个或多个网络连接为公共连接的错误,可包含`-SkipNetworkProfileCheck`开关或将连接设为私有。
此外,`Enable-PSRemoting` cmdlet仅为运行该命令的版本启用远程PowerShell。例如,在PowerShell 7会话中运行该cmdlet,不会为Windows PowerShell启用远程操作,反之亦然。
##### 2.2 WSMan PowerShell远程操作的权限
默认情况下,Administrators和Remote Management Users组的成员有权通过PowerShell远程连接到服务器。Remote Management Users组的用户通常具有标准用户的权限,除非他们在服务器上有额外权限。
对于VS Code扩展场景,需授予用户管理员权限,因为他们需要读取每个用户配置文件中的文件。
##### 2.3 使用WSMan PowerShell远程操作执行命令
远程服务器设置好后,即可开始执行远程命令。接下来要确定如何执行远程操作并记录结果,可使用控制脚本调用之前创建的`Get-VSCodeExtensions.ps1`脚本,此控制脚本也可用于在多个不同系统上执行其他所需脚本。
使用`Invoke-Command` cmdlet时,脚本文件只需本地客户端可访问,无需远程服务器可访问。也可传递脚本块,这适用于一到两行的命令,但传递复杂脚本时,最好将其保存为单独的脚本文件,这样可使控制脚本可重用,避免命令硬编码。
需为`Invoke-Command` cmdlet提供远程服务器。前面讨论过,要使用`New-PSSession` cmdlet为每台机器创建持久会话,然后将所有会话作为数组传递给`-Session`参数。这样还能隔离未能建立连接的特定机器,以便单独修复。
创建远程会话数组时,要确保只将成功的连接添加到数组中。若将未连接的会话添加到数组,再将该数组传递给`Invoke-Command`,会出错且远程服务器上不会运行任何命令。为防止这种情况,可将`New-PSSession`命令包装在`try/catch`中,并将`-ErrorAction`参数设置为`Stop`。若`New-PSSession`出现错误,脚本将自动跳转到`catch`块,跳过`try`块中的其他所有行:
```powershell
try{
$session = New-PSSession -ComputerName $s -ErrorAction Stop
$Sessions.Add($session)
}
catch{
Write-Host "$($s) failed to connect: $($_)"
}
```
控制脚本的最后一步是添加用于收集所有返回数据的列表以及CSV导入和导出。
整个过程的最后一步是关闭远程会话。使用`New-PSSession` cmdlet创建会话后,该会话会在本地客户端和远程服务器上保持活动状态,使用`Remove-PSSession` cmdlet可关闭会话,释放远程服务器的资源并关闭两台机器之间的连接。
以下是一个使用WSMan远程操作对远程计算机执行本地脚本的示例:
```powershell
$servers = 'Svr01', 'Svr02', 'Svr03' # 要连接的服务器数组
$CsvFile = 'P:\Scripts\VSCodeExtensions.csv' # 保存结果的路径
$ScriptFile = 'P:\Scripts\Get-VSCodeExtensions.ps1' # 脚本文件路径
$ConnectionErrors = "P:\Scripts\VSCodeErrors.csv" # 记录连接错误的另一个CSV文件
if (Test-Path -Path $CsvFile) { # 检查CSV文件是否存在
$csvData = Import-Csv -Path $CsvFile |
Select-Object -ExpandProperty PSComputerName -Unique
$servers = $servers | Where-Object { $_ -notin $csvData }
}
[System.Collections.Generic.List[PSObject]] $Sessions = @()
foreach ($s in $servers) { # 连接到每台服务器并将会话添加到$Sessions数组列表
$PSSession = @{
ComputerName = $s
}
try {
$session = New-PSSession @PSSession -ErrorAction Stop
$Sessions.Add($session)
}
catch {
[pscustomobject]@{ # 将任何错误添加到连接错误CSV文件
ComputerName =
```
0
0