powershell - 让 psessions 为 txt 文件中列出的多个服务器正确循环时出现问题

标签 powershell powercli vmware-tools

我从一个名为 vms.txt 的 txt 文件开始。

它包含 2 个服务器,如下所示:

server1
server2

当我运行下面所示的脚本时,调用来安装 VMware 工具的命令仅在 server2 上运行,而 server1 会被跳过。有人对如何修改此脚本以使其在 txt 文件中的两台服务器上运行有任何建议吗?将来我将不得不在数百个虚拟机上运行它,因此我正在尝试找到一种简单的方法来使其正确循环。

$cred = Get-Credential
$vms = Get-Content C:\Scripts\Tools\vms.txt

foreach($vm in $vms){
$sessions = New-PSSession -ComputerName $vm -Credential $cred
}

foreach($session in $sessions)
{
Invoke-Command -Session $session -ScriptBlock {
c:\users\jsmith\documents\VMware-tools-10.3.5.exe /v "/qn REBOOT=R Remove=AppDefense,VMCI”
}
} 

最佳答案

在基于循环的方法中,问题在于变量分配:

# !! This only ever stores the *last* session created in $sessions,
# !! because the assignment is performed in *each iteration*.
foreach($vm in $vms){
  $sessions = New-PSSession -ComputerName $vm -Credential $cred
}

立即修复是将作业移出循环:

# OK - captures *all* session objects created in $sessions
$sessions = foreach($vm in $vms){
  New-PSSession -ComputerName $vm -Credential $cred
}

退后一步:

两者New-PSSession -ComputerNameInvoke-Command -Session 接受计算机名称/ session 的数组,因此不需要循环

  • 多个 session /计算机名称传递给Invoke-Command具有操作运行的巨大优势>并行

  • 注意:

    • Invoke-Command 具有内置限制,以避免一次针对太多计算机。默认为 32,但可以使用 -ThrottleLimit 参数进行修改。
    • 来自目标计算机的输出将以不可预测的顺序到达,但输出对象用(除其他外)反射(reflect)原始计算机的 .PSComputerName 属性进行修饰 - 请参阅 this answer 的底部部分.

也就是说,您的代码可以简化为:

$cred = Get-Credential
$vms = Get-Content C:\Scripts\Tools\vms.txt

$sessions = New-PSSession -ComputerName $vms -Credential $cred

Invoke-Command -Session $sessions -ScriptBlock {
  c:\users\jsmith\documents\VMware-tools-10.3.5.exe /v "/qn REBOOT=R Remove=AppDefense,VMCI”
}

重要:

  • session 最终应使用 Remove-PSSession 进行清理当不再需要时。
  • 但是,这会停止在这些 session 中运行的任何命令,因此,如果您通过 Invoke-Command 调用启动了异步操作,则需要确保这些操作首先已完成 - 请参阅下面有关 VMware-tools-10.3.5.exe 应用程序可能异步执行的注释。

或者,更简单的是,如果您只需要在每台计算机上执行一个命令,在这种情况下不需要显式创建 session ,则传递所有计算机名称直接到 Invoke-Command-ComputerName 参数:

$cred = Get-Credential
$vms = Get-Content C:\Scripts\Tools\vms.txt

# Note the use of -ComputerName
Invoke-Command -ComputerName $vms -Credential $cred -ScriptBlock {
  # Note the use of | Write-Output to ensure synchronous execution.
  c:\users\jsmith\documents\VMware-tools-10.3.5.exe /v "/qn REBOOT=R Remove=AppDefense,VMCI” | Write-Output
}

重要:

  • 如果您的应用程序 (VMware-tools-10.3.5.exe) 异步运行,您必须确保其 同步执行,否则可能无法运行完成,因为当脚本 block 从给定计算机返回时,隐式创建的远程 session 将被丢弃。

  • 确保任何外部(GUI 子系统)可执行文件同步执行的一个简单技巧是将其通过管道传输到 Write-Output,如上所示(或 Wait-Process,如果它不产生控制台输出) - 请参阅 this answer以获得解释。

关于powershell - 让 psessions 为 txt 文件中列出的多个服务器正确循环时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71773661/

相关文章:

powershell - powercli Get-VM 不匹配标签

powershell - 列出 VM 及其集群

linux - fatal error : Module sg not found

vagrant - `Waiting for HGFS kernel module to load`期间出现 `vagrant up --provider=vmware_fusion`错误

vmware - vmware工作站工具Mountain Lion Mac OS X

powershell - 使用 dbPoweramp Powershell 降低 CPU 使用率

c# - 序列 API : Authenticating using Integrated Security?

excel - 在宏 VBA 中将操作参数传递给 SchTasks

powershell - 在 powershell 中生成文本序列

c# - 对于 vSphere 和 vCenter 自动化,PowerCLI cmdlet 还是 VIX API 是更好的方法?